5.2.14. Address Tables Object

Sometimes you need to apply a rule to a set of addresses, but you don't know what those addresses will be when you're writing the policy. The address table object object can help in these situations.

Figure 5.60. The Address Table Object

The Address Table Object

The address table object has the following fields:

  • Name:

    The name of the address rable object.

  • Compile Time / Run Time:

    Indicates whether you want the file to be loaded with the firewall compiler runs (Compile Time) or when the firewall runs the firewall script (Run Time).

  • File name:

    The name of the text file you want to load. (The file contains IP addresses or IP address ranges.) The filename can have any extension. If you want the file to load at run time, you must specify the path and name where the file will be on the firewall machine, not on the client machine.

  • Choose File button:

    Used to populate the file name and path if the file is on the local machine. You can also type in a path to a filename that you want to create.

  • Edit File button:

    Once the File name field is populated, use this button to view and update the file. If the file does not already exist, Firewall Builder will generate a warning message.

  • Comment:

    A free-form text field used for comments

The Compile Time and Run Time radio buttons define when the addresses will be read from the file: when the firewall script is generated by Firewall Builder or when the firewall runs the script.

If object is configured as Compile Time, the Firewall Builder policy compiler opens the file during compilation and replaces the address table object in policy rules with the set of addresses from the file. This means the file with addresses must be accessible on the machine where the Firewall Builder GUI and policy compilers run.

If the object is configured as Run Time, policy compiler does not try to find and open the file but instead generates a firewall script that will do this when it is activated. This means the file with addresses must be located where it is accessible by the firewall, and the object must be configured with the full path to it on the firewall.

Here is an example of the file contents (this is what you see if you click the Edit File button in the object dialog):

Figure 5.61. Address Table Text File

Address Table Text File

Note that comments in the file can start with "#" or ";", that a comment can follow an address on the same line or take the whole line, and that lines can start with white space for formatting. This example file contains both IPv4 and IPv6 addresses for illustration purposes.

Compile-time address table objects are supported on all target firewall platforms because addresses are read by the compiler. The compiler then generates normal configuration lines or script commands. Run-time address table objects require special support from the target firewall and are therefore supported only on some of them. Currently run-time address table objects can be used in rules for iptables and PF firewalls.

Let's look at the firewall script generated by Firewall Builder for the iptables and PF when the Address Table object used in the policy rule is configured first as "Compile Time" and then as "Run Time". The rule is very simple and looks like (Figure 5.62):

Figure 5.62. Rule Using an Address Object

Rule Using an Address Object

This rule, with the object set to Compile Time, generates the following output:

Figure 5.63. Compile Time, iptables Compile Output

# Rule 0 (global)
# 
$IPTABLES -A INPUT  -d 192.168.1.1  -j DROP 
$IPTABLES -A FORWARD  -d 192.168.1.2  -j DROP 
$IPTABLES -A FORWARD  -d 192.168.1.3/30  -j DROP 
$IPTABLES -A FORWARD  -d 192.168.2.128/25  -j DROP 
$IPTABLES -A FORWARD  -d 192.168.1.200  -j DROP 
$IPTABLES -A FORWARD  -d 192.168.1.201  -j DROP 

The compiler replaced the object address_table_1 in the Destination with addresses it took from the file. Option assume firewall is part of any was turned off in the firewall object settings, which is why compiler did not generate rules in the OUTPUT chain. However, one of the addresses in the file matched the address of one of the interfaces of the firewall (192.168.1.1) and the corresponding rule went into the INPUT chain. Other addresses were copied from the file verbatim, including netmask specifications. The policy object of this firewall was configured as "IPv4 rule set", because of this the compiler dropped the IPv6 addresses it found in the file. If the rule set was configured as a mix of IPv4 and IPv6, compiler would use IPv4 addresses in IPv4 rules and IPv6 addresses in IPv6 rules.

Figure 5.64. Compile Time, PF Compile Output

# Tables: (1)
table  { 192.168.1.1 , 192.168.1.2 , 192.168.1.3/30 , 192.168.2.128/25 , \
192.168.1.200 , 192.168.1.201 }

# Rule  0 (global)
# 
block in   quick inet  from any  to <tbl.r0.d>
block out  quick inet  from any  to <tbl.r0.d>


The output for PF is simple because Firewall Builder can use the built-in table facility. All addresses are copied from the file verbatim into the table tbl.r0.d.

Figure 5.65. Run Time, iptables Compile Output

# Using 1 address table files
check_file "address_table_1" "/home/vadim/addr-table-1.tbl"

# Rule 0 (global)
# 
grep -Ev '^#|^;|^\s*$' /home/vadim/addr-table-1.tbl | while read L ; do
  set $L; at_address_table_1=$1; $IPTABLES -A FORWARD  -d $at_address_table_1  -j DROP 
done

First, the generated script checks if the file specified in the address table object exists on the firewall machine. If the file is not found, the script aborts execution to avoid loading incomplete iptables rules. However, the script cannot verify that the file is the one you intended it to be; it just assumes that if the file with this name exists it is the right one and tries to interpret it as a list of IP addresses, with one address per line. Then the script reads the file line by line, skipping comments, and assigns IP addresses to the shell variable at_address_table_1, which it then uses in the iptables command.

Since the compiler did not see the addresses from the file, it could not detect that one of them matched an address of the firewall and all iptables commands went to the FORWARD chain. The file /home/vadim/addr-table-1.tbl should be located on the firewall where the generated iptables script will be executed so the script can find it.

Here is what you get if the option "Assume firewall is part of any" is turned on in the firewall object settings:

Figure 5.66. Run Time, iptables Compile Output: assume firewall is part of "any"

# Rule 0 (global)
# 
grep -Ev '^#|^;|^\s*$' /home/vadim/addr-table-1.tbl | while read L ; do
  set $L; at_address_table_1=$1; $IPTABLES -A OUTPUT  -d $at_address_table_1  -j DROP 
done
grep -Ev '^#|^;|^\s*$' /home/vadim/addr-table-1.tbl | while read L ; do
  set $L; at_address_table_1=$1; $IPTABLES -A FORWARD  -d $at_address_table_1  -j DROP 
done

The difference is that compiler generated two sets of commands, one in chain OUTPUT and another in chain FORWARD. The original rule has "any" in source, and if the option Assume firewall is part of any is turned on, the compiler assumes the source of the rule can have either an unknown address or the firewall. The former makes it generate iptables command in the FORWARD chain and the latter makes it generate iptables command in the OUTPUT chain. This logic is not specific to the address table object type; the compiler does this regardless of the type of the object used in destination if source is "any" and option Assume firewall is part of any is turned on.

Figure 5.67. Run Time, PF Compile Output

# Tables: (1)
table  persist file "/home/vadim/addr-table-1.tbl"
# Rule  0 (global)
# 
# 
block in   quick inet  from any  to <address_table_1>
block out  quick inet  from any  to <address_table_1>

PF is even easier in the case of run time address tables. The compiler just uses table facility with persist and file options to direct pfctl to open the file and read its contents. In this case, the file should follow the formatting requirements of PF.

Policy compiler for PF treats address table objects with empty file name in a special way. It just generates the line "table <table_name>" at the beginning of the .conf file with no file specification. This table will not be populated when .conf file is loaded and therefore will remain empty, but it can be used in the rules.

Addresses can be added to the table later using external scripts that call pfctl like this:

Figure 5.68. Using pfctl to add a host to the table

pfctl -t bad_hosts -T add 192.0.2.1
      

Another interesting possibility is to automatically populate the table if option "overload" is used in combination with other rate limiting options on a rule. Taking an example from the man page for pf.conf, here is how it looks:

Figure 5.69. Example using the "overload" command to auto populate a table

block quick from <bad_hosts>
pass in on $ext_if proto tcp to $webserver port www keep state \
                   (max-src-conn-rate 100/10, overload <bad_hosts> flush global)
            

The idea behind these rules is that if some host tries to connect to the web server too often -- more often than is allowed by max-src-conn-rate 100/10 -- its address will be added to the table <bad_hosts> by PF. The next time this host tries to connect, the packet coming from it will be denied by the blocking rule right away.

To implement these rules in Firewall Builder, you would create an Address Table object with the name "bad_hosts" but a blank file name, configured to resolve at run time:

Figure 5.70. Address Table Object bad_hosts

Address Table Object bad_hosts

Then, use this address table object in the source field of a policy rule with action "Deny". This is rule #0 in the screenshot below. Another rule, rule #1 in the screenshot, has action "Accept" and matches destination against address of the web server, protocol http, and has limiting options set up to restrict the number of connections and to turn overload table on, with the name of the overload table "bad_hosts" that matches the name of the address table object.

Figure 5.71. Address Table Object bad_hosts Rules

Address Table Object bad_hosts Rules

These two rules, as shown on the screen shots, yield the following PF configuration that matches the one given in the man page:

Figure 5.72. Example pf rules using table objects

# Tables: (1)
table <bad_hosts> persist

# Rule  0 (global)
# 
block in   log  quick inet  from <bad_hosts>  to any 
# 
# Rule  1 (global)
# 
pass in   quick inet proto tcp  from any  to 192.168.1.1 port 80 \
   keep state  (  max-src-conn-rate 100/10, overload <bad_hosts> flush global ) 

            

5.2.14.1. Using Address Tables Objects with iptables IP Sets

Beginning with Firewall Builder version 4.1, there is support for iptables firewalls to use the netfilter ipset module. The ipset module provides a method for storing a list of IP addresses or IP subnets in memory. This allows firewall administrators to define a single iptables rule that matches multiple IP addresses or IP subnets as the source and/or destination. In Firewall Builder an "ipset" is associated with an address table object where the list of addresses and subnets are defined in a file.

Using the IP sets feature requires an iptables version of at least 1.4.1.1 and requires that the target firewall have the ipset module installed. There are instructions for installing the ipset module for some distributions described in the Appendix Section 16.1.1. If you have installation instructions for installing the ipset module on a distribution not listed in the Appendix please e-mail info@fwbuilder.org.

You can find more information about the netfilter ipset module at the netfilter IP sets page.

NOTE: Testing if your iptables firewall supports IP set

To test if your firewall has the ipset module and ipset tools installed run the following commands from a shell. Note you must be root or have sudo rights to run the command.

Test to check if ipset tools are installed

fwadmin@guardian:~$ sudo ipset --version
ipset v2.5.0 Protocol version 2.
fwadmin@guardian:~$
    

Test to check if ipset module is installed

fwadmin@guardian:~$ sudo ipset -N test iphash
FATAL: Module ip_set not found.
ipset v4.1: Couldn't verify kernel module version!
fwadmin@guardian:~$
    

To enable the iptables "IP sets" functionality in Firewall Builder, you must explicitly set the version of the iptables firewall that you want to use with the ipset module. Navigate to the firewall and double-click to open the object in the editor window. Set the iptables version number to a version that is at least 1.4.1.1.

Figure 5.73. Set the firewall iptables version number

Set the firewall iptables version number

After you have set the iptables version number, click Firewall Settings for this firewall. Near the bottom of the Firewall Settings dialog window you there is a checkbox that says:

Use module "set" for run-time address table objects. (This module is only available in iptables v 1.4.1.1 and later.)

Select this checkbox to enable using the iptables ipset module.

Figure 5.74. Set the Firewall Settings to Use the "IP set" Module

Set the Firewall Settings to Use the "IP set" Module

If the checkbox and text are shown as greyed out, then go back and check that you set the iptables version number for this firewall.

You can only use address tables that are set to Run Time with the ipset module. Compile Time address table objects will behave as before with the objects in the specified file being expanded when the firewall is compiled.

NOTE: Mixed IP addresses and IP Subnets in "IP Sets"

Normally the ipset module requires you to create separate "sets" for IP addresses and IP subnets. Firewall Builder, through its abstraction layer, enables you to create mixed IP addresses and IP subnets in the same file. This creates what is known as a "set list" that contains two "sets", one "set" that includes only IP addresses and another "set" that includes only IP subnets.

The following example shows the Firewall Builder configuration steps for setting up an Addresss Table called "bad_hosts", using that address table in a rule, and confirming the ipset configuration.

Figure 5.75. Address Table Object

Address Table Object

Figure 5.76. Editing the Address Table File

Editing the Address Table File

Figure 5.77. Rule Using Address Table Object

Rule Using Address Table Object

You can use the ipset tools to view the configuration of your "sets" once they have been created by Firewall Builder on your firewall. For example, the command ipset --list will list all the configured "sets" on your firewall.

If you install a firewall that is using address tables with ipset enabled you can update the list of addresses that are stored in memory for that "set" by updating the file associated with the address table object and then running the firewallscript.fw reload_address_table command. For the examples shown above you would enter:

guardian.fw reload_address_table bad_hosts /etc/fw/bad_hosts
    

where "guardian.fw" matches the name of your Firewall Builder script file and "bad_hosts" is your address table object. This dynamically updates the list of addresses stored in memory for the bad_hosts set while iptables is running.

NOTE: Naming Convention for Address Table Objects and "Sets"

When Firewall Builder creates the "set" it substitutes an underscore ("_") for any spaces. For example, the address table named "My Address List" would have a "set" name of "My_Address_List". Also, note that the name of the address table object cannot start with colon (":") due to restrictions in the ipset module.

There are two primary benefits of using the ipset module. First, the performance for matching a single rule that is using a set to hold a large number of addresses is better than having individual rules for each of these addresses. Second, the ipset module and tools provide a way to dynamically update the addresses in a list while the firewall is still running.

 

Copyright © 2000-2012 NetCitadel, Inc. All rights reserved.
 Using free CSS Templates.