FF_ Firewall_iRule
Problem this snippet solves:
I wrote this iRule since I needed a way to handle ACL-based firewalling on LTM. The code relies on a datagroup that holds the ACLs. The iRule itself needs to be applied to an LTM "IP Forwarding" Virtual Server, listening on 0.0.0.0/0.0.0.0 all protocols and on all VLANs that have to secured by this "ACL-based Firewall".
Code :
# # FF Firewall iRule for TMOS v10 # 2011 Fabrizio Fiorucci# # Release history: # 20110217 - 0.1 - Initial release # 20110218 - 0.2 - Improved datagroup lookup speed, full support for subnets (src and dest) and wildcard ports and for TCP/UDP/ICMP # # This iRule relies on a String datagroup called "ACL_Datagroup" that contains a list of allowed ACLs # Datagroup entries format is: # DSTIP DSTPORT PROTOCOL/ICMP_TYPE := SRCIP SRCPORT # # Examples: # 85.18.58.110 110 6 := 172.30.30.0/24 0 # 85.18.58.110 22 17 := 172.30.30.40 0 # 93.62.218.238 8 1 := 172.30.30.40 0 <-- If protocol is 1 (ICMP) dstport is the ICMP type (8 for echo request) # # Protocol numbers taken from /etc/protocols (1=ICMP, 6=TCP, 17=UDP) # # Sample Datagroup is: # # class ACL_Datagroup { # { # "65.61.115.222 80 6" { "192.168.1.0/24 0" } # "65.61.115.222 443 6" { "192.168.1.1 0" } # "8.8.8.8 8 1" { "192.168.0.0/16 0" } # "8.8.8.8 53 17" { "192.168.0.0/16 53" } # } # } # # That defines the following ACLs: # allow from 192.168.1.0/24 (all src ports) to 65.61.115.222 TCP/80 # allow from 192.168.1.1/32 (all src ports) to 65.61.115.222 TCP/443 # allow from 192.168.0.0/16 (all src ports) to 8.8.8.8 ICMP/Echo Request (ICMP type 8) # allow from 192.168.0.0/16 (src port 53/UDP) to 8.8.8.8 UDP/53 # when CLIENT_ACCEPTED { set fw_debug 1 set dropRequest 1 set src_ip [IP::client_addr] set src_port [TCP::client_port] set dst_ip [IP::local_addr] set dst_port [TCP::local_port] set request_protocol [IP::protocol] set dumpRequest "\[$src_ip\:$src_port\] -> \[$dst_ip\:$dst_port\] protocol $request_protocol" if { $fw_debug } { log local0. "Checking request: $dumpRequest" } # Looks up destination IP, destination_port/icmp_type and protocol (x.x.x.x port proto) set ACLDstLookup "$dst_ip $dst_port $request_protocol" set ACLMatchedList [class get ACL_Datagroup $ACLDstLookup] if { $fw_debug } { log local0. "Destination $ACLDstLookup found [llength $ACLMatchedList] matches" } if { [llength $ACLMatchedList] == 0 } { if { $fw_debug } { log local0. "No ACL found for $dumpRequest - trying for wildcard dstport" } set ACLMatchedList [class get ACL_Datagroup "$dst_ip 0"] if { $fw_debug } { log local0. "Destination $ACLDstLookup found [llength $ACLMatchedList] wildcard dstsport matches" } if { [llength $ACLMatchedList] == 0 } { if { $fw_debug } { log local0. "No ACL found for $dumpRequest with wildcard dstport" } discard } } # ACL List is built like { DSTIP DSTPORT } { SRCIP SRCPORT } # thus we need to skip all items in odd-numbered positions foreach thisACL $ACLMatchedList { if { $thisACL equals $ACLDstLookup } { if { $fw_debug } { log local0. "Skipping odd-numbered item $thisACL" } } else { if { $fw_debug } { log local0. "Checking ACL $thisACL" } set thisACLSrcIP [lindex $thisACL 0] set thisACLSrcPort [lindex $thisACL 1] if { [IP::addr $src_ip equals $thisACLSrcIP] || [IP::addr 0.0.0.0 equals $thisACLSrcIP] } { if { $fw_debug } { log local0. "ACL Source IP Matches" } if { $src_port == $thisACLSrcPort || $thisACLSrcPort == 0 } { if { $fw_debug } { log local0. "ACL Source Port Matches, forwarding $dumpRequest" } set dropRequest 0 # Match found, exits foreach loop break } else { if { $fw_debug } { log local0. "ACL Source Port doesn't match, dropping" } } } else { if { $fw_debug } { log local0. "ACL Source IP doesn't match, dropping" } } } } if { $dropRequest == 1 } { if { $fw_debug } { log local0. "Dropping $dumpRequest" } discard } else { if { $fw_debug } { log local0. "Forwarding $dumpRequest" } forward } }
Published Mar 17, 2015
Version 1.0Fabrizio_Fioru1
Historic F5 Account
Joined January 15, 2008
Fabrizio_Fioru1
Historic F5 Account
Joined January 15, 2008
No CommentsBe the first to comment