Sample INSPECT Code

Now that I have talked about how INSPECT works and how your rulebase translates to INSPECT code, I can show you some sample INSPECT code.

WARNING!

graphics/lightning_icon.gif

Exercise appropriate caution before implementing any of this code in a production network. This includes testing in a nonproduction environment to ensure the code does what you expect.


Check Point allows you to place custom INSPECT scripts in $FWDIR/lib/user.def. Check Point does not overwrite this file during an upgrade; therefore, it is the recommended location for any custom INSPECT code. All INSPECT changes should be done on the management console. A policy reinstall is required after any of these types of changes in order for them to take effect.

Allowing Outbound Connections to SecuRemote Clients

Allowing outbound connections to SecuRemote clients was mentioned in Chapter 12, but it is worth bringing up again simply because it can be used as an example of INSPECT code. Recall that the quandary was how to allow a connection on port TCP 5555 to a particular machine only if it were an authenticated SecuRemote client. Whenever a SecuRemote client successfully authenticates to FireWall-1, an entry is created in the table userc_rules: <ip, 0>. This is so FireWall-1 knows to encrypt all traffic to this IP address. You can also use this table entry as a basis for allowing a service. Create a service of type Other. The protocol number will be 6 (for TCP). The following will be in the Match field:

dport=5555,<dst,0> in userc_rules

This service will accept the packet if it is of type TCP. Its destination port (service) is 5555, and the entry <dst,0> appears in the table userc_rules. As you will recall from Table 14.2, dst means the destination IP address of the current packet.

Point-to-Point Tunneling Protocol

Another example of INSPECT code is useful for the service Point-to-Point Tunneling Protocol (PPTP), which is defined in RFC2637, only because it uses a variation of the GRE protocol. Normally, to allow GRE through FireWall-1, you need to create two services:

  1. TCP port 1723 for a control session

  2. A variation of the GRE protocol (IP protocol 47) for data

Create the latter service as a service of type Other. Use 47 for the protocol number. For the Match field, enter:

[22:2,b] = 0x880B

This code indicates that you are using PPTP embedded in GRE (you look at the 22nd and 23rd bytes together to see if they equal 880B).

NOTE!

graphics/brain_icon.gif

PPTP is not supported with hide NAT, only static NAT. This is due to the fact that the transport mechanism used does not lend itself to many-to-one IP address translations.


Allowing a Connection Based on a Previous Connection

There is a particular application available that uses UDP destination port 3000 for both packets originating from the client as well as replies coming from the server. If the application were normal, the client would send packets to the server on UDP port 3000, but the reply packets coming from the server would have a UDP source port of 3000. FireWall-1 doesn't normally handle services that communicate in this manner. In order to allow this service, you need to generate custom INSPECT code.

Because you need to write code to catch certain types of reply packets, you need to add some code to $FWDIR/lib/user.def. You want to accept the packet if and only if the first packet is accepted. You can create an entry in a table for that specific kind of packet and look for entries in that table later.

First, create a service of type Other. Since this is UDP, the protocol number will be 17. You do not need to check Accept Replies because you are going to do that in your own code. In the Match field for this service of type Other, you need the following:

dport=3000, record <src,0,dst,3000,ip_p> in accepted_udp

Now you need some code to catch the reply packets. In $FWDIR/lib/user.def, add the following lines between the #ifdef and the #endif in the file:

all@oscar
     accept udp, dport=3000, <dst,src,dport,ip_p> in accepted_udp;

Finally, you need to create the table accepted_udp. It cannot be done in user.def because the actual service appears in the INSPECT script before the user.def file is referenced. In FireWall-1 4.1 and earlier, services of type Other had a mechanism called Prologue, which allowed you to define tables and such prior to the service definition. Unfortunately, this means modifying a file that will get changed on an upgrade. $FWDIR/lib/table.def seems the most appropriate choice for this purpose. Here is the code to add to that file, prior to the ending #endif:

accepted_udp = table {} sync keep;

Now you can use this new rule in a rulebase and install the security policy.

NOTE!

graphics/brain_icon.gif

The method used to deal with the UDP port 3000 service effectively adds three table entries: two in the connections table (one for the connection in each direction) and one in the accepted_udp table.


Different Rules for Different Interfaces

SmartDashboard/Policy Editor does not allow different rules for different interfaces, but INSPECT does. You could take an existing .pf file and simply change the rules to apply only to a specific interface. The following example was used previously. The only change made below is that all@oscar becomes eth-s2p1c0@oscar. This means that the rule applies only on interface eth-s2p1c0.

eth-s2p1c0@oscar
 accept     eitherbound, start_rule_code(7),
     (udp, l2tp),
     (ip_dst in ip_list19),
     RECORD_CONN(7),
     LOG(long, LOG_NOALERT, 7), ALLOW_TEMPLATE_ACCELERATION

NOTE!

graphics/brain_icon.gif

FireWall-1 Virtual System Extension (VSX) implements something similar to this within the VSX version of SmartDashboard/Policy Editor. Each virtual system is made up of specific interfaces. Internally, FireWall-1 compiles these rules in terms of the specific interfaces that make up that virtual system. Thus, a single copy of FireWall-1 can effectively serve multiple virtual systems concurrently.


Changing Your Default Filter

The default filter is the security policy that loads when FireWall-1 starts up before it attempts to load a policy from the management console. If FireWall-1 fails to load a policy, the default filter remains active until a new policy is manually loaded. FireWall-1 comes with several such policies:

  • defaultfilter.boot, installed by default, allows all outgoing as well as incoming communications on ports that had previous outgoing communications. ICMP and broadcast packets are also allowed.

  • defaultfilter.drop drops all communication into the gateway except for established connections.

  • defaultfilter.ipso allows SSH (port 22) and HTTPS (port 443) to the gateway, dropping everything else.

  • defaultfilter.ipso_ssh allows SSH to the gateway, dropping everything else.

  • defaultfilter.ipso_ssl allows HTTPS to the gateway, dropping everything else.

FireWall-1 4.1 and earlier gave you the ability to switch default filters in fwconfig or cpconfig. You can switch to a particular default filter manually by executing the following commands (in the following example, defaultfilter.ipso is used):

# rm $FWDIR/state/default.bin
# cp $FWDIR/lib/defaultfilter.ipso $FWDIR/conf/defaultfilter.pf
# fw defaultgen
# cp $FWDIR/state/default.bin $FWDIR/conf/default.bin

On a Windows platform, the commands below are used:

C:> del %FWDIR%\state\default.bin
C:> copy %FWDIR%\lib\defaultfilter.ipso %FWDIR%\conf\defaultfilter.pf
C:> fw defaultgen
C:> copy %FWDIR%\state\default.bin %FWDIR%\conf\default.bin

NOTE!

graphics/brain_icon.gif

Users of Nokia Horizon Manager will have the default filter changed to defaultfilter.ipso during the initial install/upgrade of a Nokia platform. This allows Nokia Horizon Manager to manage the platform despite FireWall-1 not being fully configured.


The next obvious question might be, "Can I write my own default filter?" Certainly, if you know how to write INSPECT code. The following caveats apply: The INSPECT script in question must not include any of the default .def files from $FWDIR/lib. You must define everything you need to use as part of the script. When you are ready to compile the script, it needs to be placed in $FWDIR/conf/defaultfilter.pf, which is where fw defaultgen expects to find the script.

Keep in mind that this policy is a fail-safe policy, not a policy that will generally be used. IP Forwarding will typically be disabled, so the firewall will not be able to forward packets unless you tell FireWall-1 to not control IP Forwarding (which is not recommended). As a result, this policy is relevant only to packets originating from or going to the firewall.

Appendix F provides a sample default filter policy that accepts packets coming to port 22 (SSH) or port 256 (FireWall-1 management protocol), which permits you to load a policy to the firewall or SSH to the firewall for further management. Remember that IP Forwarding should be disabled on the platform, so even if a packet destined for another host is permitted by this policy, it will not be forwarded past the firewall.

fw monitor

fw monitor is similar to a packet sniffer and is built into FireWall-1. Secure Client NG FP3 also includes this functionality as srfw monitor. It shows you how packets are entering and exiting the FireWall-1 kernel module. Because FireWall-1 resides just above the MAC layer, fw monitor cannot be used to see layer 2 traffic, but it can still be useful as a packet sniffer for layer 3 and above, and it can also be used to monitor multiple interfaces simultaneously.

NOTE!

graphics/brain_icon.gif

On IPSO 3.3 and later, when Flows is enabled in the IPSO kernel (it is by default), fw monitor shows only the initial packet exchange for TCP and UDP. This is because the IPSO kernel handles the inspection and forwarding of packets that have been flowed directly in the kernel, which increases performance and throughput. FireWall-1 never sees the flowed packets.


This command is documented in this chapter instead of Chapter 10 on NAT, where it might also be appropriate, because INSPECT is necessary to make use of fw monitor. Usage for this command is as follows:

fw monitor [-d] [-D] -e inspect-filter -f filter-file
           [-l len] [-m mask] [-x offset[,len]] [-o file]

There are four inspection points as packets pass through FireWall-1. You choose where you want to see packets with the -m option:

  • Before FireWall-1 processes the packet in the inbound direction (i or PREIN)

  • After FireWall-1 processes the packet in the inbound direction (I or POSTIN)

  • Before FireWall-1 processes the packet in the outbound direction (o or PREOUT)

  • After FireWall-1 processes the packet in the outbound direction (O or POSTOUT)

Because there can be lots of packets, you need some way to determine which packets you are interested in seeing. You do this by means of an INSPECT filter, which can be typed in directly on the command line or provided via an INSPECT filter file. One of the options -f or -e is required; these are described in Table 14.4.

Table 14.4. Command-line options for fw monitor

Flag

Description

-d

Turns on debugging

-D

Turns on debugging

-e script

Specifies an INSPECT script via the command line

-f filename

Specifies an INSPECT script contained in filename

-l numbytes

Specifies the number of bytes to capture in each packet

-m mask

Specifies inspection points mask (any one or more of i, I, o, or O as explained in the text)

-o outfile

Specifies an output file in Solaris snoop format

-x offset,len

Performs a hex dump of received data, starting at specified offset, showing len bytes

Once you execute this command, FireWall-1 compiles the specified INSPECT script (either on the command line or in a file), loads it into the kernel module, and displays the packets in the terminal window or prints them to an output file, which is a Solaris snoop format. FireWall-1 continues to do this until an interrupt signal is sent to the program (Ctrl-C) or another security policy is loaded, after which it will unload the filter and exit.

The INSPECT script should return an accept in order for packets to be displayed. Any other return code causes packets to not be displayed. If you want to catch packets only on a certain interface, do not use le0@all (for example), but instead use direction=x,ifid=y (where x is 0 for inbound and 1 for outbound, and y is an interface number returned by the fw ctl iflist command). Do not use table names that are used by the security policy.

Table 14.4 lists the command-line options for fw monitor.

Examples

The following code line displays all TCP packets entering and leaving FireWall-1.

fw monitor -e '[9:1]=6, accept;' -l 100 -m iO -x 20

Although 100 bytes of data are captured for each packet, up to 80 bytes of TCP header and data will be displayed starting at offset 20 (assuming no IP options are used).

The following code line displays all packets entering and exiting FireWall-1 in the inbound direction (i.e., before the operating system routes the packet).

fw monitor -e 'accept;' -m iI

The following code line displays all packets entering interface ID 0 that are coming from or going to 10.0.0.1. The value used for ifid corresponds to a number given to an interface by FireWall-1. You can determine which interface has which number by using the command fw ctl iflist.

fw monitor -e 'accept ifid=0,src=10.0.0.1 or dst=10.0.0.1;'

The following code line does the same thing as the previous command except that it looks for packets of IP protocol 47 only.

fw monitor -e 'accept ifid=0,src=10.0.0.1 or dst=10.0.0.1,ip_p=47;'

The following code line displays all TCP packets going to or coming from 10.0.0.1 with either a source port of 80 or a destination port of 80.

fw monitor -e 'accept tcp,dport=80 or sport=80,src=10.0.0.1
             or dst=10.0.0.1;'

Warnings

Here are some important notes about using fw monitor.

  • Do not alter tables used in the security policy; unexpected behavior (including a system crash) may result if you do.

  • Packets are defragmented as the packets leave FireWall-1 in both the inbound and outbound directions.

  • Anything that causes a fetch, load, or unload of your security policy will cause fw monitor to terminate.

  • All INSPECT code used in srfw monitor (for Secure Client) should be in RAW format, which means no macros from tcpip.def or other places. If you don't feel like figuring this out yourself, try using Joost De Cock's ginspect tool, available at http://www.bdc-networks.be/joost/ginspect.php.