Forum Discussion
iRule to extract SNI and forward to Virtual Server
Hey guys,
Currently I use traffic policies on a frontside VS to inspect the SNI and forward the traffic to a backside VS properly. I tried to use an iRule instead because sometimes traffic policies are a bit nasty to configure. Anyways, I deployed this simple iRule
when CLIENTSSL_CLIENTHELLO priority 100 {
set sni [SSL::extensions -type 0]
log local0. "Client SNI: $sni"
if { $sni equals "fqdn.com" } {
virtual vs-https443-fqdn.com
} else {
drop
}
}
The log says this
<CLIENTSSL_CLIENTHELLO>: Client SNI: �����������fqdn.com
The forwarding does not work. I think it's binary. I was able to trim away these characters
set sni [string range [SSL::extensions -type 0] 9 end]
and the forwarding worked out. I thought I had to trim 10 characters (indexing starts with 0, not 1) but I had to use 9 because the first character of the FQDN has been removed. Any ideas on this?
However, it works. What would be your approach to solve this? And lastly is there a possibility to decode the binary stuff?
This looks great Lucas. Line 6 is missing the close quote. To make it map fqdn's to virtuals, I assume it would look like this:
when CLIENTSSL_CLIENTHELLO priority 100 { if {[SSL::extensions exists -type 0]} { binary scan [SSL::extensions -type 0] @9a* SNI if {[regexp {(?i)[^a-z0-9.-]} $SNI]} { log local0. "CLIENTSSL_CLIENTHELLO client offered bogus SNI: $SNI" } elseif {[info exists SNI] && ($SNI equals "fqdn-a.com")} { virtual a #log local0. "CLIENTSSL_CLIENTHELLO client offered this SNI: [string tolower $SNI]" } elseif {[info exists SNI] && ($SNI equals "fqdn-b.com")} { virtual b #log local0. "CLIENTSSL_CLIENTHELLO client offered this SNI: [string tolower $SNI]" } } }
- spalandeNacreous
SNI-based routing is easy and efficient using local traffic policy. Why complicate using iRule? Please refer below article
- seamlessfireworkCirrostratus
Thanks for your reply. Well, yes, traffic policies are easy in a way. On the other hand they feel not native to me in the BIG-IP ecosystem. I can't explain that exactly, it's very subjective. Also, configuring a traffic policy through REST is kind of complicated: create a draft, add the configuration, publish the policy. Changing an iRule is one single POST.
- DanSkowCirrus
I assume you'd either have to add a binary scan event to the iRule, or change the logic from "equals fqdn.com" to "contains fqdn.com" or "ends_with fqdn.com"
- Lucas_ThompsonEmployee
I think you're missing one step to post-process the data.
This iRule snippet is used within SSL Orchestrator to catch the SNI so it's been tested extensively.
if {[SSL::extensions exists -type 0]} { binary scan [SSL::extensions -type 0] @9a* SNI if {[regexp {(?i)[^a-z0-9.-]} $SNI]} { log local0. "CLIENTSSL_CLIENTHELLO client offered bogus SNI" } else { log local0. "CLIENTSSL_CLIENTHELLO client offered this SNI: [string tolower $SNI] } }
- DanSkowCirrus
This looks great Lucas. Line 6 is missing the close quote. To make it map fqdn's to virtuals, I assume it would look like this:
when CLIENTSSL_CLIENTHELLO priority 100 { if {[SSL::extensions exists -type 0]} { binary scan [SSL::extensions -type 0] @9a* SNI if {[regexp {(?i)[^a-z0-9.-]} $SNI]} { log local0. "CLIENTSSL_CLIENTHELLO client offered bogus SNI: $SNI" } elseif {[info exists SNI] && ($SNI equals "fqdn-a.com")} { virtual a #log local0. "CLIENTSSL_CLIENTHELLO client offered this SNI: [string tolower $SNI]" } elseif {[info exists SNI] && ($SNI equals "fqdn-b.com")} { virtual b #log local0. "CLIENTSSL_CLIENTHELLO client offered this SNI: [string tolower $SNI]" } } }
- seamlessfireworkCirrostratus
Thanks a lot that worked great!
I added some (cosmetical) improvements. The irule VS code extension suggested to add "--" after the regexp because of argument injection. So I added it.
when CLIENTSSL_CLIENTHELLO priority 100 { if { [SSL::extensions exists -type 0] } { binary scan [SSL::extensions -type 0] @9a* client_sni if { [regexp -- {(?i)[^a-z0-9.-]} $client_sni] } { log local0. "CLIENTSSL_CLIENTHELLO client offered bogus SNI: $client_sni" } elseif { [info exists client_sni] && ($client_sni equals "fqdn-a.com") } { virtual a log local0. "CLIENTSSL_CLIENTHELLO client offered this SNI: [string tolower $client_sni]" } elseif { [info exists client_sni] && ($client_sni equals "fqdn-b.com") } { virtual b log local0. "CLIENTSSL_CLIENTHELLO client offered this SNI: [string tolower $client_sni]" } else { drop } } }
Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com