HLFL SYNTAX ----------------------------------------------------------------------------- hlfl are a list of statements. Each statement have the following syntax : protocol (local) operator (remote) [interface] keywords 'local' is the network you want to protect 'remote' is the network you want to be protected from Example : tcp (192.168.1.1) <-> (192.168.2.1) [eth0] Means in bsd ipfw language : ipfw -f add allow tcp from 192.168.1.1 to 192.168.2.1 out via eth0 ipfw -f add allow tcp from 192.168.2.1 to 192.168.1.1 in via eth0 And this means in a human language : 'protect 192.168.1.1 from 192.168.2.1' all (any) X (any) Means : ipfw -f add deny all from any to any List of operators : ----------------------------------------------------------------------------- -> : accept outgoing <- : accept incoming <-> : accept outgoing and incoming <=>> : accept outgoing and incoming if the communication was established <<=> : accept outgoing and incoming if the communication was established by the remote side X : deny incoming and outgoing X! : reject incoming and outgoing X-> : deny outgoing <-X : deny incoming X!-> : reject outgoing <-X! : reject incoming Note that <=>> and <<=> work for UDP on stateful firewalls. On stateless firewall, they work the same way as <-> for UDP. (src) and (dst) format ------------------------------------------------------------------------- (src) and (dst) can be : (ip ports) ie : (192.168.1.1 1-1024) (192.168.2.1 21,22,80,49152-65535) Or : (ip ports | other_ip other_ports | ....) ie : (192.168.1.1|192.168.1.12|192.168.1.200) Several sources can be combined with several destinations : tcp (192.168.1.1|192.168.2.1|192.168.3.1) <=> (172.22.0.1|172.22.0.2|172.22.0.3) Means : 192.168.1.1 can communicate with 172.22.0.1, 172.22.0.2 and 172.22.0.3 192.168.2.1 can communicate with 172.22.0.1, 172.22.0.2 and 172.22.0.3 192.168.3.1 can communicate with 172.22.0.1, 172.22.0.2 and 172.22.0.3 The keyword 'nomix' can be added at the end of a line, in this case, tcp (192.168.1.1|192.168.2.1|192.168.3.1) <=> (172.22.0.1|172.22.0.2|172.22.0.3) nomix means : 192.168.1.1 can communicate with 172.22.0.1 192.168.2.1 can communicate with 172.22.0.2 192.168.3.1 can communicate with 172.22.0.3 tcp (192.168.1.1 80 | 192.168.2.1 21) X (172.22.0.1) is a valid statement. It prevents 172.22.0.1 to communicate with 192.168.1.1 on port 80 and 192.168.2.1 on port 21 Finally, tcp ((192.168.1.1|192.168.2.1) 80,21) X (172.22.0.1) is a valid statement which prevents 172.22.0.1 to communicate with 192.168.1.1 and 192.168.2.1 on ports 21 and 80 ICMP ------------------------------------------------------------------------------- The following icmp types are recognized : echo-request echo-reply destination-unreachable time-exceeded To have a working 'ping' : icmp (any echo-request) -> (any) icmp (any) <- (any echo-reply) Variables ------------------------------------------------------------------------------- It is possible to define variables to make the rules more readable, using the keyword 'define' define word value ie : define inside 192.168.1.0/24 define public_ports 1024-65535 (inside public_ports) <=>> (any) Include ------------------------------------------------------------------------------ It is possible to include a file using the 'include' instruction. Example : o in def.hlfl : define ftp 21 define ssh 22 define telnet 23 o in rules.hlfl : include def.hlfl tcp (any ssh) <<=> (any) Comments ------------------------------------------------------------------------------- There are three kinds of comments that are handled by hlfl : - comments starting by '%' will *not* be included in the generated file. That is : % % This rules are written in hlfl % tcp (any) -> (any) Will produce, in ipchains format : ipchains -A output -s 0/0 -d 0/0 -j ACCEPT - comments starting by '#' will be included in the generated file, except when cisco rules are selected. That is : % % This rules are written in hlfl % # allow all the outgoing tcp tcp (any) -> (any) Will produce : # allow all the outgoing tcp ipchains -A output -s 0/0 -d 0/0 -j ACCEPT - Comments starting by '!' will be included as COMMANDS in the generated file. This reduces portabilty, since your rules will depend of the underlying firewall, but this is convieniant in some cases (typically, if you play with forwarding, masquerading, and so on...) !ipchains -A forward -s 0/0 -d 0/0 -i eth0 -j ACCEPT tcp (any) -> (any) Will produce : ipchains -A forward -s 0/0 -d 0/0 -i eth0 -j ACCEPT ipchains -A output -s 0/0 -d 0/0 -j ACCEPT Note that if you select the ipfw output, you'll get this nonnense : ipchains -A forward -s 0/0 -d 0/0 -i eth0 -j ACCEPT ipfw add allow tcp from any to any out So you can define conditional inclusion. That is : ! if(ipchains) ipchains -A forward -s 0/0 -d 0/0 -j eth0 -j ACCEPT In that case, this rule will only be printed if you are generating ipchains output. Note that the 'else' statement is *not* supported. Real-life examples ------------------------------------------------------------------------------- See sample_1.hlfl and sample_2.hlfl