Alter.Org.UA  
 << Back Home RU ru   Donate Donate www/www1/www2

Patches for IPFW

by Alter (alterX@alter.org.ua (remove X))

  • adds commands zshow (zero+show), replace (del+add)
  • option -Q for ignoring ALL errors
  • skipto tablearg
  • via table(), you can insert interface name into table
  • condition if-index - number of interface (e.g. for vlan55 it would be 55) (deprecated)
  • indexing of rules in kernel (index table) for fast handling of skipto tablearg, and effective add/remove of large amount of rules.
  • mapped table - for tables containing many single IPs (e.g, /32) we perform large subnet lookup via b-tree (e.g, /23, controlled by sysctl net.inet.ip.fw.def_map_mlen), and inside each /23 perform table lookup. Works much faster.
  • map table - hash-based division of large IP block on several small ones. For example, /16 can be divided into 256 subnets. We can do it by 3rd octet (hoffset 16, hlen 8). Also, we can do it by 4th octet (hoffset 24, hlen 8). hoffset defines number of the 1st bit of hash, hlen - hash length in bits. Also, we define base IP and netmask for map table to match large IP block.
  • packet/byte counter for each table element
  • indexed pipe lookup table (controlled by sysctl net.inet.ip.dummynet.full_indexing)
  • traffic counter/limiter - count-upd, count-check, count-exceed.
  • nexthop ipfw action. In contrast to fwd it just sets next-hop for packet and continue rule procesing.
  • optimized dummynet io_fast. Value 2 makes dummynet just forwarding packet without placing to the queue, if bandwith limit is not exceeded. When value is set to 1 packet is added and then immediately removed from queue (it is bit slower).
  • it is possible to use bmap instead of port list. It gives performance benefit when you have large list of services. Lookup time doesn't depend on list size. Rather useful to QoS game traffic.
  • Fast ipfw tagging (ftag) - you can assign up to 32 ftags on packet. All ftags are stored in single memory block as bitmap. Are faster than usual tags, those allocate separate memory block for each tag.
  • Local ipfw tagging (ltag) - you can assign up to 32 ltags on packet. Ltags are not preserved when packet leaves ipfw ruleset (e.g. is sent to another interface, diverted or passed through pipe). The benefit is performance - ltag does not require memory allocation at all.


Patch download:
9.2-STABLEipfw.92.20150115.patch.gz all-inclusive
9.2-STABLEipfw.92.single-patchs.rar/tgz (109.4 Kb/129 Kb) separated patchs
7.2-RELEASE-p8ipfw.72.20120614u.patch.gz all-inclusive

Patchs for IPFW, 9.2-RELEASE.

There is cumulative patch including features described above. Also you can apply single updates separately via ipfw.92.single-patchs.rar/tgz (109.4 Kb/129 Kb)

Patchs for IPFW, 7.2-RELEASE.

ipfw.72.20120614u.patch.gz

Includes all features described above. You can find examples of usage below

FreeBSD bugtrack ID: 156770

Patch is compatible with 7.3 and 7.4 except conflict with (yet unused)

#define	IP_FW3			48   /* generic ipfw v.3 sockopts */
#define	IP_DUMMYNET3		49   /* generic dummynet v.3 sockopts */
in in.h


Example 1
# interface-based dispatch
ipfw table 1 add %vlan516 55
ipfw table 1 add %em0 10
ipfw add 1 skipto tablearg ip from any to any via table(1)

# IP-based dispatch
ipfw table 60 add mapped 192.168.0.2  1602
ipfw table 60 add mapped 192.168.0.3  1603
ipfw table 60 add mapped 192.168.0.4  1604
ipfw add 2 skipto tablearg ip from any to table(60)

# port-based dispatch (TCP/UDP only)
ipfw bmap 13 add 25,137-139,445
ipfw add 3 deny ip from any to any dst-port bmap(13)

# Limit traffic amount for some IPs
ipfw counter create 4096  # init counter table, up to 4096 items
ipfw counter add @2 set-limit 10g # init counter 2 with 10Gb limit
ipfw counter add @4 set-limit 10g # init counter 4 with 10Gb limit
ipfw counter set-limit @2 5g # reconfig counter 2 with 5Gb limit
# make dispatch table
ipfw table 50 add mapped 192.168.0.2  2
ipfw table 50 add mapped 192.168.0.4  4
# update counters
ipfw add 4 count ip from any to table(50) count-upd tablearg
# block users exceeded traffic limit
ipfw add 5 deny ip from any to table(50) count-exceed tablearg

# count traffic and block users with exceeded limit (variant 2)
ipfw add 4 deny ip from any to table(50) count-check tablearg


Example 2
#!/bin/sh
. /etc/rc.conf


# Tables
# 1  - UA
# 2  - Google peer
# 6  - local nets
# 7  - peer nets
# 8  - lan nets
# 10 - transparent proxy users
# 11 - blocked users
# 50 - UA-out
# 51 - UA-in
# 60 - W-out
# 61 - W-in

# Tags
# 1  - from UA-IX
# 2  - to UA-IX
# 6  - local traffic (directly between server and clients)
# 7  - peer traffic
# 8  - internal (lan, inter-lan) traffic

# 16 - from LOCAL (locally handled clients) - out
# 26 - to LOCAL                             - in
# 17 - from PEER
# 27 - to PEER
# 18 - from LAN   (all handled networks)
# 28 - to LAN
# 19 - from ME
# 29 - to ME


ftag=${ipfw_ftag:-"tag"}

trusted_smtp_clients="table(14)"
blocked_smtp_clients="table(15)"
local_nets="table(6)"
peer_nets=" table(7) or table(2) "
lan_nets="table(8)"
win_ports="$win_ports"

rule_game_ports_out="bmap(2)"
rule_game_ports_in="bmap(3)"

rule_win_ports="$win_ports"
rule_denied_ports="$win_ports,25"


cat > /etc/firewall.conf.1 << EOF
replace 1 allow ip from any to any
replace 51001 allow ip from any to any

# out
table 40 flush
table 40 add %$user_if   16
table 40 add %$user9_if  16
table 40 add %$user7_if  16
table 40 add %$user3_if  16
table 40 add %$user2_if  16
table 40 add %$user12_if 16
table 40 add %$user8_if  16
table 40 add %$user10_if 27
table 40 add %$user11_if 27
table 40 add %vlan522    16
table 40 add %$user88_if 16
table 40 add %$core_if   16
table 40 add %$world_if  3
table 40 add %$world0_if 3
table 40 add %lo0        4
table 40 add %vlan4089   4

# in
table 41 flush
table 41 add %$user_if   40
table 41 add %$user9_if  40
table 41 add %$user7_if  40
table 41 add %$user3_if  40
table 41 add %$user2_if  40
table 41 add %$user12_if 40
table 41 add %$user8_if  40
table 41 add %$user10_if 28
table 41 add %$user11_if 28
table 41 add %vlan522    40
table 41 add %$user88_if 40
table 41 add %$core_if   19
table 41 add %$world_if  18
table 41 add %$world0_if 18
table 41 add %lo0        19
table 41 add %vlan4089   19

#client->server DST games+http(s)+telnet+ssh+dns
bmap 2 add 53,23,22,443
bmap 2 add $game_ports
bmap 2 add $web_ports
bmap 2 add $video_ports
bmap 2 add $skype_ports
#server->client SRC games+https+telnet+ssh+dns
bmap 3 add 53,23,22,443
bmap 3 add $game_ports
bmap 3 add $video_ports
bmap 3 add $skype_ports

bmap 13 add $win_ports
bmap 14 add $win_ports
bmap 14 add 25

replace 2 skipto 5 ip6 from any to any
# separate in/out
add     2 skipto 7 ip from any to any in

# dispatch according to interface (out)
add     2 skipto tablearg ip from any to any via table(40)

replace 3 divert natd ip from { $local_nat_nets } to any
replace	4 allow ip from any to any
replace 5 allow ip6 from any to any in
add     5 allow ip6 from any to any

# allow external SMTP, block Win-ports
del 7
add     7 skipto 9 ip from any to any not $rule_denied_ports

replace 8 deny ip from { $blocked_smtp_clients } to any 25
add     8 skipto 14 tcp from { $trusted_smtp_clients } to any 25
add	8 skipto 14 tcp from { $local_nets } to { $world_mx_ip or $our_relay or me } 25
add     8 deny log { tcp or udp } from { $local_nets } to any 25
add	8 allow ip from me to me
add     8 deny { tcp or udp } from any to any $win_ports

# dispatch according to interface (in)
replace 15 skipto tablearg ip from any to any via table(41)
add     15 skipto 40 ip from any to any

# out, user if(s)
replace 16 allow ip from any to not table(11)
add     16 allow tcp from { $pay_system_ips } 80,443 to any
add     16 allow ip from me to any
add     16 deny ip from any to any

# in, world if(s)
replace 18 divert natd ip from any to $user_nat_ip
del     19
add     19 allow tag 29 ip from any to me
add     19 skipto 115 tag 26 ip from any to any

######## WiFi shapers #########

### to 37/xxx, 12/xxx
pipe 100 config delay 100ms bw 5000kbit/s
pipe 101 config bw 18000kbit/s
pipe 103 config bw 18000kbit/s
delete  27
add     27 allow icmp from any to any
add     27 allow ip from $game_servers to any
add     27 allow { tcp or udp } from any 53,23,22 to any
add     27 allow { tcp or udp } from any $rule_game_ports_in to any
add     27 pipe 100 udp from any to any
add     27 pipe tablearg ip from any to table(101)
add     27 allow tcp from any 80 to any
add     27 allow ip from any to any

### from 37/xxx, 12/xxx
pipe 102 config bw 10000kbit/s
pipe 104 config bw 8000kbit/s
delete  28
add     28 skipto 40 icmp from any to any
add     28 skipto 40 ip from any to $game_servers
add     28 skipto 40 { tcp or udp } from any to any 53,23,22,80,443
add     28 skipto 40 { tcp or udp } from any to any $rule_game_ports_out
add     28 pipe tablearg ip from table(102) to any
add     28 pipe 100 udp from any to any
add     28 skipto 40 ip from any to any

### regular rules (continue) ###

# in, user if(s)
replace 40 skipto 110 tag 16 ip from not table(11) to any
# blocked users
del 109
add     109 count untag 6 ip from any to any
add     109 count untag 8 ip from any to any
add     109 allow { tcp or udp } from any to { $master_servers or me } 53
add     109 fwd 127.0.0.1,80 tcp from any to any 80
add     109 deny ip from any to any

replace 110 skipto 111 ip from any to any not tagged 16,19
add     110 skipto 120 tag 6 ip from any to any tagged 26,29

# only local interfaces are checked here!
# so, local traffic will be checked 

replace 112 skipto 120 ip from any to any tagged 1-2,7-8
#### IN (via local) ####
add     112 skipto 115 ip from any to any out
add     112 skipto 120 tag 8 ip from any to { $lan_nets or me }
add     112 skipto 120 tag 7 ip from any to { $peer_nets }
replace 113 skipto 120 tag 2 ip from any to table(1)
add     113 skipto 19001 ip from any to any tagged 16
add     113 skipto 120 ip from any to any

#### OUT (via local) / IN (via WORLD) ####
replace 115 skipto 120 tag 8 ip from { $lan_nets or me } to any
add     115 skipto 120 tag 7 ip from { $peer_nets } to any
replace 116 skipto 120 tag 1 ip from table(1) to any

#############################
# here comes dispatch rules
#############################

replace 900  skipto 19000 ip from any to any not ftagged 1,2
replace 1500 skipto 1502 ip from any to any ftagged 26
add     1500 skipto tablearg ip from table(50) to any
add     1500 skipto tablearg ip from any to table(51)
add     1500 count ip from any to any
replace 1501 skipto tablearg ip from table(50) to any
add     1501 skipto 38000 ftag 12 ip from any to any
replace 1502 skipto tablearg ip from any to table(51)
add     1502 skipto 38000 ftag 12 ip from any to any
replace 1503 allow ip from any to any

# fill mapped dispatch table
table 50 add mapped 10.0.0.10 1600
table 50 add mapped 10.0.0.11 1610
table 50 add mapped 10.0.0.12 1620

replace 51000 allow ip from any to any

delete 1 51000
EOF

echo "$ftag"
sed -e "s/tag/$ftag/g" < /etc/firewall.conf.1 > /etc/firewall.conf.2
sed -e "s/unftag/funtag/g" -e "s/unltag/luntag/g" < /etc/firewall.conf.2 > /etc/firewall.conf.1

cp /etc/firewall.conf.1 /etc/firewall.conf
ipfw -Q /etc/firewall.conf

History

Ported to FreeBSD 9.2. Incremental patches for all features are also available.

ipfw.92.20150115.patch.gz
ipfw.92.single-patchs.rar/tgz (109.4 Kb/129 Kb)
2015.01.14

I've made unified diff to satisfy FreeBSD development standards

ipfw.72.20120614u.patch.gz
2012.06.14

Patchs for IPFW, FreeBSD 7.1-RELEASE and 7.2-RELEASE.

ipfw.72.20110501.patch.gz
2011.05.02

Patchs for IPFW, FreeBSD 7.1-RELEASE and 7.2-RELEASE.

ipfw.71.patch.gz
ipfw.72.patch.gz

Adds commands zshow, replace. -i option (ignore all errors) is united with -q. If 7.2 man clarisies meaning of error ignoring when -q is used. So, separate option -Q for ignoring all errors is revoked.

ipfw_idx.70.patch.gz
ipfw_idx.71.patch.gz
ipfw_idx.72.patch.gz

  • skipto tablearg
  • indexing of rules in kernel (index table) for fast handling of skipto tablearg, and effective add/remove of large amount of rules


    2010.01.01

    Patch for IPFW, FreeBSD 7.0-STABLE.

    ipfw.70.patch.gz

    Still adds commands zshow, replace. -i option is united with -q,


    2008.06.30

    Patch for IPFW from FreeBSD 6.3.

    ipfw.63.patch.gz

    All listed below patches

    FreeBSD bugtrack ID: 116009
    2008.06.30

    Patches for IPFW from FreeBSD 6.2-RELEASE-p5.

    all updates

    ipfw.62.patch.gz

    All listed below patches


    2007.09.03

    zshow

    ipfw-zshow.patch.gz

    Adds 'zshow' command, which shows rule counters and immediately resets them to zero. Is useful for traffic counters.

    ipfw zshow 1000
    

    2007.09.03

    ignore errors + replace

    ipfw-ignore_err_opt.patch.gz

    Adds 'replace' command, which adds rule if it doesn't exist yet or replaces existing.

    ipfw replace 200 count ip from any to any via fxp0
    

    Also adds '-i' switch to command line and ruleset file format. When '-i' is used, all rules containing errors will be rejected, but correct rules will be applied. IPFW shall not stop on the 1st invalid rule. It is useful when loading ruleset from file.

    ipfw -i /etc/firewall.conf
    

    2007.09.03


    Mail to alterX@alter.org.ua (remove X)  
  • designed by Alter aka Alexander A. Telyatnikov powered by Apache+PHP under FBSD © 2002-2017