on 14-Mar-2016 14:31
What could you do with your code in 20 Lines or Less?
That's the question we like to ask from, for, and of (feel free to insert your favorite preposition here) the DevCentral community, and every time we do, we go looking to find cool new examples that show just how flexible and powerful iRules can be without getting in over your head. Thus was born the 20LoL (20 Lines or Less) series many moons ago. Over the years we've highlighted hundreds of iRules examples, all of which do downright cool things in less than 21 lines of code.
At RSA a couple weeks ago I presented on how to secure your clients with regards to their experience on your web applications. Scott Helme created the SecurityHeaders.io site where you can test your apps to see what is and isn’t supported currently. I can’t stress enough how important it is to read carefully and test thoroughly before implementing some of these headers, you can dos yourself fairly easily. That said, putting in the work to protect your users is a worthy effort, and it’s a pretty easy implementation with iRules, or with an LTM policy. You can test CSP and HPKP using the -Report-Only trailer to those headers at another site of Scott's called Report-URI.io.
when RULE_INIT { set static::fqdn_pin1 "X3pGTSOuJeEVw989IJ/cEtXUEmy52zs1TZQrU06KUKg=" set static::fqdn_pin2 "MHJYVThihUrJcxW6wcqyOISTXIsInsdj3xK8QrZbHec=" set static::max_age 15552000 } when HTTP_REQUEST { HTTP::respond 301 Location "https://[HTTP::host][HTTP::uri]" } when HTTP_RESPONSE { #HSTS HTTP::header insert Strict-Transport-Security "max-age=$static::max_age; includeSubDomains" #HPKP HTTP::header insert Public-Key-Pins "pin-sha256=\"$static::fqdn_pin1\" max-age=$static::max_age; includeSubDomains" #X-XSS-Protection HTTP::header insert X-XSS-Protection "1; mode=block" #X-Frame-Options HTTP::header insert X-Frame-Options "DENY" #X-Content-Type-Options HTTP::header insert X-Content-Type-Options "nosniff" #CSP HTTP::header insert Content-Security-Policy "default-src https://devcentral.f5.com/s:443" #CSP for IE HTTP::header insert X-Content-Security-Policy "default-src https://devcentral.f5.com/s:443" }
We haven't featured too many DNS-based iRules, but we are starting to see an uptick in their presence in the community. The result of the conversation between dearsanky and Kai Wilke is a short but sweet sample redirecting non-existent domain queries
when DNS_RESPONSE { if { [DNS::header rcode] eq "NXDOMAIN" } { DNS::header rcode NOERROR DNS::answer insert "[DNS::question name]. 60 [DNS::question class] [DNS::question type] 1.1.1.1" } }
Another more complex DNS sample, also a result of an exchange between dearsanky and Kai Wilke. This iRule blocks queries not configured in the admin_datagroup data-group as well as looks for blacklisted ip’s and blocks those as well. Before the DNS namespace was added to iRules (note: license required if you don’t have GTM/BIG-IP DNS) this was an exercise in binary scans and formats, but is made far simpler with clear commands.
when RULE_INIT { set static::blacklist_reply_IPV4 "10.10.10.10" set static::blacklist_ttl "100" } when DNS_REQUEST { set Blacklist_Match 0 set Blacklist_Type "" set domain_name [DNS::question name] if {[DNS::header "rd"] == 1 } { if { not [class match [IP::client_addr] eq "admin_datagroup" ] } { DNS::drop } elseif { [string tolower [class match $domain_name eq Blacklist_Class]] } { set Blacklist_Match 1 DNS::return } } } when DNS_RESPONSE { if { $Blacklist_Match } { switch [DNS::question type] { "A" { DNS::answer clear DNS::answer insert "[DNS::question name]. $static::blacklist_ttl [DNS::question class] [DNS::question type] $static::blacklist_reply_IPV4" DNS::header ra "1" } default { DNS::last_act reject } } } } }
And there it is, another edition of 20 Lines or Less, the power of iRules on full display. Happy coding out there, and I look forward to seeing what excellent contributions might make the next edition!
Thanks Jason for including one (two!) of my solutions in the 20LinesOrLess series... 😉
@Jie: The
DNS::answer clear
is required in this case to sanitize the existing DNS answer, to make sure that only the blacklist response is send to the client. If you skip the DNS::answer clear
, then it may become a RR DNS response. But you could also directly DNS respond to the request using the DNS_REQUEST event (not implemented in this specific iRule). In this case you don't need to DNS::answer clear
the answer, since you would build the answer completely from the scratch...
Cheers, Kai