---
name: "hlfl"
section: "1"
platform: "linux"
package: "hlfl"
version: "0.60.1-1"
release: "Debian 4.0 (Etch)"
platforms: ["linux"]
url: "https://new.carta.tech/hlfl"
---

# hlfl(1)

High Level Firewall Language

## NAME

hlfl - High Level Firewall Language

## SYNOPSIS

**hlfl**\

- \-t or --type=

  \[ipchains \| ipfw \| ipfw4 \| ipfwadm \| ipfilter \| netfilter \| cisco \] RULEFILE\

- \-o or --output=

  FILE (stdout is the default)\

- \-h or --help

  prints help\

- \-V or --version

  prints version\

- \-c or --check

  check netmasks before computing\

- \-v or --verbose

  be verbose, print comments

## DESCRIPTION

**hlfl** is a tool which can produce several types of firewalls from a given set of rules written in a special language also called hlfl (however awkward it is).

**hlfl** attempts to make the best use of the features of the underlying firewall, so that the conversion of a stateless to a stateful requires no modification to the original script

## HLFL - THE 'LANGUAGE'

A complete description of the hlfl syntax is in ${prefix}/share/hlfl/syntax.txt Each order must fit on one line. The syntax is :

protocol (local) operator (remote) \[interface\] keywords\

Where :

- protocol

  must be one of *tcp* , *udp* , *icmp* or *all*

- (local) and (remote)

  contain the IP addresses (and tcp and udp ports) of both side. Multiple IPs may be specified.  For instance :

		(192.168.1.1 21 \| 192.168.2.1 80)\

Means 'port 21 of 192.168.1.1 or port 80 of 192.168.2.1'. The port range syntax is the same as, say, [nmap(1)](/nmap/1.md). The next statements are valid :\
\
 	tcp (192.168.1.1 21,22,1024-3128,4000-) -\> (any)\
\
  	tcp ((192.168.1.1\|192.168.2.1) 21,22,1024-) -\> (any)\

**Note** : it is very important to understand that *local* and *remote* can **not** be exchanged. *local* is the thing you want to protect, and *remote* is the other party. Be sure to understand that or your rules will not work and you won't like hlfl.

- operator

  must be one of the defined operators. The following list of operators has been defined :\
   \-\>   : accept outgoing\
   \<-   : accept incoming\
   \<-\>  : accept outgoing and incoming\
   \<=\>\>  : accept outgoing and incoming if the communication was established by the local side first\
   \<\<=\> : same as above except that the communication must be established by the remote side first\
   X-\>  : deny outgoing\
   X!-\> : reject outgoing\
   \<-X  : deny incoming\
   \<-X! : reject incoming\
   X    : deny outgoing and incoming\
   X!   : reject outgoing and incoming\

  Full text operators are allowed. The syntax is :\
   operator ::= "accept" \| "deny" \| "reject" \[ "from" \| "to" \| "and" \| "established" \| "log" \]\

  It is possible to combine full text operators with symbolic ones. This can be done for logging support.

- \[interface\]

  interface is the name of the interface to apply the rule to

- keyword

  additional keyword. At this time, only the keyword *nomix* has been defined. Imagine you write the rule:

	tcp (192.168.1.1 \| 192.168.2.1) \<-\> (172.22.0.1 \| 172.22.0.2)

If the keyword *nomix* is not added at the end of the rule, then this rule means :\
 \- accept tcp traffic between 192.168.1.1 and 172.22.0.1\
 \- accept tcp traffic between 192.168.1.1 and 172.22.0.2\
 \- accept tcp traffic between 192.168.2.1 and 172.22.0.1\
 \- accept tcp traffic between 192.168.2.1 and 172.22.0.2\

Now, if *nomix* is added at the end of the rule, then it means :\
 \- accept tcp traffic between 192.168.1.1 and 172.22.0.1\
 \- accept tcp traffic between 192.168.2.1 and 172.22.0.2\

It is possible to define words using the *define* instruction :\
\
 	define my\_net 192.168.1.0/24\
\
 	define ssh 22\
\
 	define my\_interface ne1\
\
 	tcp (my\_net 22) \<\<=\> (any 1020-) \[my\_interface\]

The *include* keyword allows you to include other files.\

	include /path/to/my/file.hlfl\
\
 	include file.hlfl\

The second *include* statement will include the file *hflf.fl* which is in the current working directory.

It is also possible to include 'systems' file, using brackets :\
\
 	include \<services.hlfl\>\

This statement includes the file ${prefix}/share/hlfl/services.hlfl, which contains the definition of common tcp and udp services.

Lines starting with '#' or '%' are treated as comments. '#' comments will be integrated in the final file, whereas '%' comments will be dropped :\
 % include myfile.hlfl which contains useful defintions\
 include myfile.hlfl\
 \# deny tcp\
 tcp (any) X (any)\

Will give, in ipfw :\
 \# deny tcp\
 ipfw -f add deny tcp from any to any\

Lines starting with a '!' will be included as commands in the generated file. This reduces portability, but this allow you to have all your firewall configuration stored in one .hlfl file. For instance, I use at home :\
 !ipchains -s 192.168.1.0 -d 0/0 -i eth1 -j MASQ\
 tcp (any) -\> (any) \[eth1\]\

I use ipchains, so I included my ipchains masquerading policy in my configuration file. If I wanted to change my firewall to something else (top-notch ipfilter because ipfilter is \_the\_ way to go), then I'll have to change (remove actually) the line starting by '!'.

It is possible to define conditional inclusion. For instance, this rule makes no sense if I am generating an ipf firewall, so the 'if( *type* )' statement exists :

% only include the following in the case we are generating an\
 % ipchains firewall. Generate a warning if we are not using\
 % ipchains

!if(ipchains) ipchains -s 192.168.1.0 -d 0/0 -i eth1 -j MASQ\
 ! else echo "Warning - NAT is not handled in this configuration"\

## EXAMPLE

see ${prefix}/share/hlfl/ for real-life examples.

## NOTE

By default, the rules are permissives, everything is allowed to pass to anywhere. If you want to change that default, add

all (any) X (any)\

at the **end** of your rules.

## OTHER INFOS

If you find some bug, please mail it to hlfl's mailing list, \<hlfl@hlfl.org\>. More details at http://www.hlfl.org/

## AUTHORS

hlfl was written by Renaud Deraison \<deraison@hlfl.org\> because the day he had to convert his ipfw firewall to ipfilter, he sweared he'd never do that again.\
 Arnaud Launay \<launay@hlfl.org\> joined later on, and took actively part in the project.\
