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".
Starting with version 2.0, Firewall Builder comes with built-in installer that uses SSH to communicate with the firewall. Installer works on all OS where Firewall Builder is available: Linux, FreeBSD, Windows and Mac OS X. On Linux, *BSD and Mac OS X it uses standard ssh client that comes with the system; on Windows it uses putty or SecureCRT.
Installer needs to be able to copy generated firewall script to the firewall and then run it there. In order to do so, it uses secure shell. On Linux, BSD and Mac OS X it uses standard ssh client ssh that comes with the system; on Windows it uses plink.exe . Full directory path to ssh client program can be configured in the Preferences dialog (accessible via Edit/Preferences menu), however if you are on Linux, *BSD or Mac and use standard ssh client that is available via your PATH environment variable, you do not need to change default value there.
You can skip this section if you run Firewall Builder on Linux, *BSD or Mac OS X.
Download and install putty.exe and plink.exe somewhere on your machine (say, in C:\putty). Download URL is http://www.chiark.greenend.org.uk/~sgtatham/putty/
Installer does not use putty.exe but it will be very useful for troubleshooting and for setting up sessions and ssh keys.
In the Edit/Preferences dialog, in the "SSH" tab, use "Browse" buttons to locate plink.exe. Hit "OK" to save preferences. If you installed it in C:\putty, then you should end up with C:\putty\plink.exe in this entry field.
You may log in to the firewall using regular user account or as root. See instructions below for an explanation how to configure sudo if you use regular user accounts. This part of the configuration does not depend on the OS you run Firewall Builder.
putty allows one to store destination host name or address, user name and bunch of other parameters in a session so that they all can be called up at once. If you wish to use sessions, do the following:
# Host alias specification Host_Alias FIREWALLS = <FWNAME>,localhost Defaults:%fwadmin !lecture # installer uses these commands Cmnd_Alias FW_INSTALL=/etc/fw/<FWNAME>.fw,/usr/bin/pkill shutdown # User alias specification %fwadmin FIREWALLS = NOPASSWD:FW_INSTALLhere <FWNAME> is the name of the firewall. Installer will log in to the firewall as user fwadmin, copy firewall script to file /etc/fw/<FWNAME>.fw and then use the following command to execute it:
ssh user@firewall sudo /etc/fw/<FWNAME>.fw
Installer needs to be able to run pkill shutdown to kill shutdown command that may be running if you tried to install policy in testing mode before. In testing mode installer copies firewall script to temporary directory /tmp then runs command shutdown -r timeout to schedule reboot in a few minutes and finally runs firewall script. To cancel scheduled reboot you need to install policy again, with test mode checkbox turned off. In this case installer will copy firewall script to its permanent place and use pkill to kill running shutdown command to cancel reboot.
$ ssh -l fwadmin <FWNAME>You may use either password or public key authentication; the installer will work either way.
Since we configured sudo to permit any member of the group "fwadmin" to execute the firewall script, this setup is ideal for the situation when several administrators need to manage the same firewall. Just add their accounts to the group "fwadmin" on the firewall and let them log in to the firewall as themselves.
$ ssh -l root <firewall_name>You may use either password or public key authentication; the installer will work either way.
See slideshow "Building simple firewall policy for Linksys firewall"
Firewall Builder logs in to the Linksys firewall as root using either password or passphrase authentication. The procedure for configuring installer is only slightly different from the method described above. On Linksys, firewall policy is stored in the NVRAM variable rc_firewall; fwbuilder uses command nvram to store policy script in this variable.
$ ssh -l root <firewall_name>You may use either password or public key authentication; the installer will work either way.
First of all, the .fwb file is portable and can be copied back and forth between Linux/BSD and windows machines. Even comments and object names entered in local language should be preserved since the GUI uses UTF-8 internally.
Built-in installer relies on path settings for ssh and scp in Edit/Preferences/SSH. Since preferences are stored outside of the .fwb file, the installer should work just fine when .fwb file is copied from Unix to Windows and back. Just configure path to ssh program in preferences on each system using default settings "ssh" on Linux and path to plink.exe on windows and give it a try.
One of the typical errors that even experienced administrators make is block ssh access to the firewall from the management workstation. You need your workstation to be able to communicate with the firewall in order to be able to make changes to the policy, so you always need to add a rule to permit this. Firewall Builder can simplify this and generate this rule automatically if you put an IP address of your workstation in the entry field on the first page of firewall settings dialog. Here is the screenshot that illustrates this setting for an iptables firewall; management station has an IP address 10.1.1.1
This script helps install and activate policy generated by the Firewall Builder on the Linux/iptables firewall.
This script has been deprecated, please use built-in installer in the GUI.
Script fwb_install has been designed to work with Linux/iptables firewall. It copies .fw file created by the policy compiler fwb_ipt over to the firewall machine and executes it there. This script is mainly used when dedicated firewall machine is controlled remotely from the management workstation. The firewall in this case should run Lunux/iptables, but the management workstation may use any supported OS, such as Linux, FreeBSD, OpenBSD, Mac OS X or Solaris. You would need to have Firewall Builder GUI and policy compiler for iptables installed on it, as well as openssh which is used to communicate with the firewall. The script fwb_install is packaged together with the GUI in the package fwbuilder (port security/fwbuilder on FreeBSD and OpenBSD or fink package fwbuilder on Mac OS X).
First of all, in order to be able to use this
script, you need to set up your ssh keys. This
procedure is well known and is discussed in details
in many only publications.
Here are few links:
Briefly, the procedure is as follows:
first, you need to generate your keys using command
ssh-keygen -t dsa
this command generates so-called DSA key used with ssh protocol v2. It will ask you for the password that will be used to protect your private key. You should use a good password, that is, it should be long, should use both letters, digits and at least few punctuation symbols and should not be a dictionary word. In other words, this password should be "strong" in a sense that it should be difficult to guess it.
Once you've created your keys, you are going to have the following files in the subdirectory .ssh in your home directory:| id_dsa | Your private key |
| id_dsa.pub | Your public key |
Now you need to transfer the public key to the firewall. First, check if the directory /root/.ssh exists on the firewall. Create it if it does not, and make its permissions to be 700 using the following commands (as root):
# cd /root # mkdir .ssh # chmod 700 .ssh
copy file id_dsa.pub to that directory under the name authorized_keys. It is the simplest to copy it using the following command:
$ scp .ssh/id_dsa.pub root@firewall:.ssh/authorized_keys
If the directory .ssh already exists on the firewall and the file authorized_keys is already there, you should append your public key to the bottom of this file rather than overwrite it. The public key is just a plain ASCII text, it is a very long single line of text.
Now you should test if ssh recognizes your keys and authentication is working. Try to connect to the firewall from the management workstation:
$ ssh root@firewall
see if it asks you for the passphrase instead of the usual prompt for the password. It should look like this:
$ ssh root@firewall Enter passphrase for key '/home/vadim/.ssh/id_dsa':
If you see the password prompt like this, then they key authentication is not working:
root@firewall's password:
the key authentication may not work if permissions on your .ssh directory or root's .ssh directory on the firewall are not correct (they should be 700, or 'drwx------' as shown by ls). The key authentication may also be disabled in the sshd configuration on the firewall, or the firewall may run some incompatible version of ssh daemon (unlikely if you are using any reasonably modern version of Linux on the firewall).
Now open your firewall object in the Firewall Builder GUI and configure it to use script fwb_install to install the policy. Open "Compile/Install" tab of the firewall object dialog, check the "Install script" checkbox and enter "fwb_install" in the "Policy Install script" entry field. Apply your changes and save the data file using main menu "Save".
Now the main menu item "Rules/Install" will get activated when you open the firewall object or one of its interface or policy objects. Use this menu to install compiled policy on the firewall machine.
When you call this menu item, the GUI will start the installation script fwb_install (you'll watch its progress in the pop-up dialog window that appears). The script starts ssh-agent to activate your keys; the agent then opens another pop-up window asking you for the passphrase for the key:
The message "The agent has no identities" is normal, it is printed by the ssh-agent and it only means that when the agent has just started, it did not load any keys yet. The passphrase it is asking you in the pop-up dialog is that password you used to protect your private key when you used ssh-keygen. Enter the passphrase in the dialog and press enter or click OK. The complete successfull installation session should look like this:
If you make a typo entering the passphrase, the ssh-agent which ask you to repeat it. If you click Cancel, then the installation script aborts with the error message "Failure adding identity, can not continue":
This error message means the firewall policy has not been transferred to the firewall and has not been activated.
One of the typical errors that you may see while using script fwb_install is "Object firewall (ID=XXXXXX) does not have management interface". The script uses management interface's address to communicate with the firewall. You need to use checkbox "Management interface" in the interface object dialog to mark one of the firewall's internal interfaces as "Management interface", which means it is the one that you plan to use to control it.
See also a manual page for this script on your system (use command "man fwb_install" to do that) or online here
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.