Chris Martin (chris.martin@iinet.net.au) wrote
excellent description of the whole process of
building Linksys router with OpenWRT and how to use
Firewall Builder to manage it. This is the most
detailed step by step document I have come across so
far, I highly recommend it. The document is
available at the following URL:
http://www.martin.cc/OpenWrt/
Here is the table of contents for a quick preview:
Overview.............................................................4
Conventions..........................................................4
Installation.........................................................5
Installing over the Linksys firmware.............................5
Installing over previous openWrt firmware........................5
ERASING NVRAM VARIABLES..........................................7
SETTING RECOVERY NVRAM VARIABLES.................................7
Configuration........................................................8
SET THE VLANS......................................................9
CONFIGURING THE LOCAL INTERFACES...................................9
CONFIGURING THE WAN INTERFACE.....................................10
WAN STATIC......................................................10
WAN DHCP........................................................11
WAN PPPOE.......................................................11
SETTING THE 802.11 PARAMETERS.....................................12
Using WPA.......................................................13
Using WEP.......................................................13
Applying MAC address restrictions...............................14
BASIC FIREWALL CONFIGURATION......................................14
STARTING THE INTERFACES...........................................16
DNS AND DHCP SERVERS..............................................17
Sample /etc/hosts...............................................17
Sample /etc/ethers..............................................17
Sample /etc/dnsmasq.conf........................................18
Force the router use dnsmasq for local lookups..................18
Starting the modified dnsmasq configuration.....................19
Configuring Remote Syslog.......................................20
Advanced Configuration..............................................21
UPDATE THE BASE PACKAGES..........................................21
INSTALL NAS.......................................................21
INSTALL TCPDUMP...................................................21
INSTALL AND CONFIGURE OPENNTPD....................................22
CONFIGURING DYNDNS IP ADDRESS UPDATES.............................23
CONFIGURING CRON..................................................24
USING HOTPLUG SCRIPTS.............................................24
(OPENSWAN) IPSEC..................................................26
(PPTPD) WINDOWS VPN...............................................28
Using Firewall Builder (fwbuilder)..................................30
CONFIGURING OPENWRT...............................................30
Restrictions....................................................30
Install packages................................................30
Load logging module.............................................30
Create the fwbuilder script file................................30
Adding the pkill script.........................................31
Modify openWrt start-up script..................................31
Running the firewall script via hotplug.........................35
CONFIGURING FIREWALL BUILDER......................................36
FIREWALL SETTINGS.................................................37
HOST OS SETTINGS..................................................42
PREFERENCE SETTINGS...............................................43
Utilities...........................................................45
DYNDNSUPD - DYNDNS UPDATE UTILITY.................................45
SPINLOCK ENSURE THAT ONLY ONE COPY OF A SCRIPT RUNS AT ONCE......50
PKILL PROCESS KILL............................................53
Appendix............................................................54
CRONTAB FILE FORMAT...............................................54
MINI_SENDMAIL COMMAND REFERENCE...................................55
MODIFY /ETC/INIT.D/S10BOOT........................................56
ADDING A SECONDARY IP ADDRESS TO AN INTERFACE.....................57
FW LOG WATCHER....................................................58
SERIAL CABLE......................................................59
Here's what I have done to get this working with the least possible user intervention. This is with a standard ethernet DHCP connection to the net, not PPP or PPPoE.
ifdown vlan1and then
ifup vlan1
and iptables was reconfigured after each step.
Here is the part of the script /usr/share/udhcpc/default.script with modifications highlighted in red:
#!/bin/sh
# udhcpc script edited by Tim Riker <Tim@Rikers.org>
# (slightly modified for OpenWrt)
[ -z "$1" ] && echo "Error: should be run by udhcpc" && exit 1
RESOLV_CONF="/tmp/resolv.conf"
case "$1" in
deconfig)
ifconfig $interface 0.0.0.0
## next line courtesy of Chris Martin
/usr/bin/spinlock /etc/wonka-firewall.fw
;;
renew|bound)
ifconfig $interface $ip \
netmask ${subnet:-255.255.255.0} \
broadcast ${broadcast:-+}
## next line courtesy of Chris Martin
/usr/bin/spinlock /etc/wonka-firewall.fw
Script spinlock has been contributed by Chris MArtin <chris@martin.name>
#!/bin/sh
#########################
# Tunable Parameters
#########################
# How long to wait for a lock to clear in seconds
SPINWAIT=300
kill_locked_process ()
{
# Arguments passed
# $1 = process to kill PID
# This will attempt to kill a locked process
KILL_PID=$1
if [ "$KILL_PID" != "" ] && [ $KILL_PID -gt 100 ]
then
# log what we are doing
ps | grep $KILL_PID | while read LINE
do
logger -p info "$0: Time out waiting for lock, terminating process: $LINE"
done
# terminate the process
kill $KILL_PID 2>/dev/null
# wait a bit for process to die
sleep 5
# try again with extreme prejudice
kill -15 $KILL_PID 2>/dev/null
fi
}
wait_for_lock()
{
# $1=Patience interval
# PATIENCE is how long to wait for the lock to free up
PATIENCE=$1
PATIENCE=${PATIENCE:-SPINWAIT}
# start time
START_PID=0
START_TIME=$(date +%s)
# check if there is a semaphore/lock file
# does file exist and length gtr 0
while [ -s $SPINLOCK_FILE ]
do
# check if the process is running
read LOCK_PID < $SPINLOCK_FILE
[ "$LOCK_PID" != "" ] && kill -0 $LOCK_PID 2>/dev/null || break
# check that no-one else got the lock while we where sleeping
[ "$START_PID" = 0 ] && START_PID=$LOCK_PID
[ "$START_PID" != "$LOCK_PID" ] && (START_PID=$LOCK_PID; START_TIME=$(date +%s))
# check if we have been waiting tooooo long (ie: run out of patience)
[ $(expr $(date +%s) - $START_TIME) -gt $PATIENCE ] && kill -9 $LOCK_PID
# wait a bit
sleep 5
done
# attempt to acquire the lock
echo "$$" > $SPINLOCK_FILE
}
clear_lock()
{
# after program is complete, clear the lock
> $SPINLOCK_FILE
}
verify_lock()
{
# verify that we got the lock
read LOCK_PID < $SPINLOCK_FILE
case "$LOCK_PID" in
$$)
# we have the lock
trap clear_lock 0 9 15
return 0;
;;
*)
# Not our lock
return 1;
esac
}
usage()
{
# display usage information
ME=$(basename $0)
echo "usage: $ME "
echo "multiple commands should be placed in a script"
exit 1
}
#######################################
# START
#######################################
# check that this is called with parameters
[ $# -ne "1" ] && usage
# work out required Commands & Parameters
SPINLOCK_FILE=/tmp/$(basename $1).pid
# Spin waiting for the lock
while :
do
wait_for_lock
if verify_lock
then
# Run the command
"$@"
# remove the lock
clear_lock
# bye
exit
fi
done
You may want to move objects between data files sometimes, for example if you used to maintain several .xml or .fwb files and want to merge them into one file. This simple HOWTO describes the method that allows you to do it.
Reminder: Objects in Firewall Builder are distinguished by their internal unique ID which is normally not visible to the user. Two objects may have the same name and other attributes and won't create a conflict, provided their IDs are different. The conflict does happen when you import objects from external file and two objects have identical Ids but some of their attributes are different. The program presents you with the dialog and asks which object you intend to keep.
In Firewall Builder 3.0 you can simply open both data files in the GUI and drag and drop (or copy/paste) objects from the tree in one window into the tree in another. If you copy complex object, such as a host or a firewall, all its children objects are copied automatically. This means when you copy firewall object, the program also copies its interfaces, their addresses and all the policies. In addition to this, the GUI finds all objects and groups used in rules and copies them too.
Suppose we have a data file old_file.fwb with a library "User" in it and want to move all objects from that library to library "old objects" in the file new_file.fwb.
If libraries in the old_file and new_file have the same name, then you'll end up with duplicate names in the drop-down list. This is normal because objects may have identical names. Just rename one of the libraries so you can distinguish them.
You can move objects from one library to another using function "Move to" of the context menu that appears if you right click on an object in the tree. You can also select several objects in the tree and then right click to open context menu to perform an operation on all of them. Following with our example, this way you can move objects from library "User" to library "new objects" and then get rid of the library "User" (which as you remember came from the file old_file.fwb). The result is that you have merged all objects into the library "new objects".
For OpenBSD pf fwbuilder puts firewall policy in the file firewall.conf and activation script in firewall.fw
To activate the policy copy both files to the directory /etc on the firewall machine using fwbinstaller. Fwbinstaller executes the activation script to install the policy immediately. Activation script not only loads PF rules, it also configured aliased IP addresses on the firewall's interfaces which is important if you use multiple addresses for NAT and want fwbuilder to configure them for you. It also sets kernel parameters defined in the "Network" tab of the firewall dialog (such as IP forwarding etc.) In order to make the firewall activate it at a boot time, call firewall script from the file /etc/rc.local as follows:
/etc/firewall.fw
If you do not want to use activation script provided by fwbuilder, you can use standard mechanisms supplied by OpenBSD. Edit file /etc/rc.conf as follows:
pf=YES # Packet filter / NAT pf_rules=/etc/firewall.conf # Packet filter rules file pflogd_flags= # add more flags, ie. "-s 256"
For ipfw fwbuilder generates policy in the form of a shell script (just like for iptables).
To install the policy, copy generated script to /usr/local/etc/ directory using ssh and then execute it. To make the firewall run this script at a boot time make the following modifications to the /etc/rc.conf file:
firewall_enable="YES" # Set to YES to enable firewall functionality firewall_script="/usr/local/etc/firewall.fw" # Which script to run to set up the firewall
On FreeBSD fwbuilder generates firewall policy in three files. Assuming firewall object's name is firewall, these files are firewall-ipf.conf, firewall-nat.conf, firewall.fw. First two files contain configuration for ipfilter, while the last one is a shell script that activates it. This script can also configure aliased IP addresses on firewall's interfaces which is important if you use multiple addresses for NAT and want fwbuilder to configure them for you.
The simplest way to activate generated policy and to make sure it is activated at boot time is to put all three filess in /usr/local/etc/ directory modify script /etc/rc.conf by adding the following lines:
firewall_enable="YES" # Set to YES to enable firewall functionality firewall_script="/usr/local/etc/firewall.fw" # Which script to run to set up the firewall
You can use script fwbinstaller to copy all three generated files from the firewall management workstation to the firewall machine.
See also excellent mini-HOWTO:
"Deploy fwbuilder-generated policy
to remote FreeBSD-and-ipfilter-based firewall" by Daniel Podolsky
Another option is to copy generated files firewall-ipf.conf and firewall-nat.conf to the directory /etc/ on the firewall machine using names ipf.rules and ipnat.rules and then use standard way of loading ipfilter policy. In order to activate it, edit file /etc/rc.conf by adding the following lines to it:
ipfilter_enable="YES" # Set to YES to enable ipfilter functionality ipfilter_program="/sbin/ipf" # where the ipfilter program lives ipfilter_rules="/etc/ipf.rules" # rules definition file for ipfilter, see # /usr/src/contrib/ipfilter/rules for examples ipnat_enable="YES" # Set to YES to enable ipnat functionality ipnat_program="/sbin/ipnat" # where the ipnat program lives ipnat_rules="/etc/ipnat.rules" # rules definition file for ipnat
It depends on what Linux distribution your firewall is based on. Firewall Builder generates the policy in a form of a shell script for the firewall based on Linux and iptables. To activate policy at a boot time you need to execute this script at a boot time one way or another.
The universal method is to put generated script in /etc or /etc/firewall directory and add a line at the bottom of script /etc/rc.d/rc.local (Mandrake and RedHat), /etc/rc.local (Debian, Ubuntu and derivatives) or /etc/init.d/boot.local (SuSE) like this:
/etc/firewall/firewall.fw
This way, firewall script runs when machine executes boot-time scripts. The name of the file is the same as the name of the firewall object in Firewall Builder GUI, with extension ".fw". So, if firewall object name is guardian, then fwbuilder puts generated policy in the file guardian.fw.
Since the firewall policy generated by fwbuilder is installed by running this script at a boot time, any other firewall startup script that might be supplied by the vendor of your Linux distribution should be disabled. On Mandrake and RedHat this can be done using command
"chkconfig --level 2345 iptables off"On SuSE use command
chkconfig -eand change state of services as follows:
SuSEfirewall2_final off SuSEfirewall2_init off SuSEfirewall2_setup offThere must be better way to turn firewall off on SuSE but I do not know it.
Another method to get firewall policy automatically installed at boot time uses scripts supplied by Mandrake or RedHat. You still need to copy generated script to the firewall machine and execute it there (this can be done using installer scripts fwb_install or fwbinstaller). Once the policy has been tested and works as expected, you just execute command "service iptables save" to save the policy. Now the policy will be activated at a boot time if service iptables is active. You can make it active on Mandrake and RedHat using command
"chkconfig --level 2345 iptables on"
Note: script generated by Firewall Builder does more than just set iptables rules, it also adds virtual IP addresses to the interfaces of the firewall and configures kernel parameters. It can get real IP addresses of interfaces with dynamic addresses and checks if interfaces are present and "up" at the time when firewall policy is applied. Standard scripts iptables-save and iptables-restore only manage iptables rules; other tasks performed by the script generated by Firewall Builder will not be done upon reboot if you use this method.
Firewall policy script generated by fwbuilder for iptables firewall needs to be restarted every time IP address of a dynamic interface changes. This article explains why is it so and how this can be done.
iptables firewall policy script generated by the Firewall Builder determines IP addresses of all dynamic interfaces and assigns them to variables which it then uses in the policy rules. This helps to build rules that require knowing address of the interface correctly, such as anti-spoofing rules. On the other hand, if interface's address changes after the policy has been loaded and activated, the firewall script needs to be restarted.
The firewall can be restarted from one of the scripts that get called by PPP or DHCP daemons whenever connection is established or new address lease is obtained. For example, DHCP daemon distributed with all major Linux distributions calls script /etc/dhclient-exit-hooks when new DHCP lease is obtained. To restart the firewall, just create file /etc/dhclient-exit-hooks and call your firewall script from it:
#!/bin/sh /etc/firewall/firewall.fw
See man page dhclient-script(8) for a detailed explanation.
On SUSE you should really be using YAST to configure this. Start Yast control center, go to "System", then "Editor for /etc/sysconfig files" in the right panel, and when the editor appears, choose "Network/DHCP/DHCP client" in the tree and edit "DHCLIENT_SCRIPT_EXE".
PPP daemon calls script /etc/ppp/ip-up when connection is established and IP address obtained. This script can be used to restart the firewall as well. Just like with /etc/dhclient-exit-hooks, just add a call to /etc/firewall/firewall.fw at the bottom of /etc/ppp/ip-up
Note: Everywhere here /etc/firewall/firewall.fw should be replaced with the real name of the firewall script. Firewall Builder stores firewall commands in the file with the name the same as the name of the firewall object, with an extension ".fw".
Note: Currently Firewall Builder requires restart of the firewall script only on iptables firewalls. Firewalls based on OpenBSD pf do not require this because pf can dynamically load IP address of the interface when it changes. As of the moment of this writing, on ipfilter and ipfw firewalls address of the dynamic interface has to be entered in the GUI, or it can not be used in the rule. This limitation will be removed in the future versions of the product.
Copyright © 2000-2008 NetCitadel, LLC. All rights reserved.
Free CSS Templates.