For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

Forum Discussion

bongshanks's avatar
bongshanks
Icon for Nimbostratus rankNimbostratus
Dec 26, 2017

Scan command and variables in a SSL transaction

Hey folks,

I'm trying to finish an iRule and I'd appreciate some critiquing or advice. I'm trying to capture some client IP/SSL cipher information as well as a 23 character string of text that will be divided up into two identifiers.

  1. I think the two log statements (Client Accept and Client handshake) are redundant and can go away

  2. I have a regular expression line after the scan command. I have verified that the regex line actually works, but I'm not confident about the scan commmand. All I know is that regex is really looked down upon.

  3. Variables. Ugh. I'm learning TCL. I left the three main variables "empty" then I have the log command fill them out. I believe this is the right way, but I'm probably wrong.

when CLIENT_ACCEPTED {
      log local0. "SSL_CUSTOM: Connection of Client Source IP: [IP::client_addr]:[TCP::client_port]<-->[virtual name]<-->[LB::server]"
    }
    when CLIENTSSL_HANDSHAKE {
      if { [SSL::cipher bits] > 0 } then {
      log local0. "Client: [IP::client_addr] is using [SSL::cipher version]. SSL Cipher:[SSL::cipher name]. Virtual:[virtual]. SSL Profile:[PROFILE::clientssl name]."
      SSL::collect
      }
    }
    when CLIENTSSL_DATA { 
        set combo ""
        set tid ""
        set mid ""
        set combo [scan [SSL::payload] ([0-9]{8}[0-9]{15}){1}]
        set tid [string range $combo 0 7]
        set mid [string range $combo 8 end]  
        log local0. "Client: [IP::client_addr] is using [SSL::cipher version]. SSL Cipher:[SSL::cipher name]. Virtual:[virtual]. SSL Profile:[PROFILE::clientssl name]. MID is $mid. TID is $TID."
        SSL::release
    } 

11 Replies

  • I'm trying to capture some client IP/SSL cipher information as well as a 23 character string of text that will be divided up into two identifiers.

    are the 23 chars in http request? if yes, isn't it easier to just use http_request event? ssl::payload is http request.

    e.g.

    // config
    
    root@(ve13a)(cfg-sync In Sync)(Active)(/Common)(tmos) list ltm virtual bar
    ltm virtual bar {
        destination 172.28.24.10:443
        ip-protocol tcp
        mask 255.255.255.255
        pool foo
        profiles {
            clientssl {
                context clientside
            }
            tcp { }
        }
        rules {
            qux
        }
        source 0.0.0.0/0
        source-address-translation {
            type automap
        }
        translate-address enabled
        translate-port enabled
        vs-index 4
    }
    root@(ve13a)(cfg-sync In Sync)(Active)(/Common)(tmos) list ltm rule qux
    ltm rule qux {
    when CLIENT_ACCEPTED {
      log local0. "SSL_CUSTOM: Connection of Client Source IP: [IP::client_addr]:[TCP::client_port]<-->[virtual name]<-->[LB::server]"
    }
    when CLIENTSSL_HANDSHAKE {
      if { [SSL::cipher bits] > 0 } then {
        log local0. "Client: [IP::client_addr] is using [SSL::cipher version]. SSL Cipher:[SSL::cipher name]. Virtual:[virtual]. SSL Profile:[PROFILE::clientssl name]."
        SSL::collect
      }
    }
    when CLIENTSSL_DATA {
      log local0. [SSL::payload]
      SSL::release
    }
    }
    
    // client
    
     curl -ik https://172.28.24.10
    HTTP/1.1 200 OK
    Date: Wed, 27 Dec 2017 01:06:34 GMT
    Server: Apache/2.2.3 (CentOS)
    Last-Modified: Fri, 15 Apr 2016 03:55:49 GMT
    ETag: "418e44-6a-fc825b40"
    Accept-Ranges: bytes
    Content-Length: 106
    Content-Type: text/html; charset=UTF-8
    
    
    
    
    
    
    This is 101 host.
    
    
    
    
    // log
    
    [root@ve13a:Active:In Sync] config  tail -f /var/log/ltm
    Dec 27 08:56:49 ve13a info tmm[17969]: Rule /Common/qux : SSL_CUSTOM: Connection of Client Source IP: 172.28.24.1:32806<-->/Common/bar<-->/Common/foo 0
    Dec 27 08:56:49 ve13a info tmm[17969]: Rule /Common/qux : Client: 172.28.24.1 is using TLSv1.2. SSL Cipher:ECDHE-RSA-AES128-GCM-SHA256. Virtual:/Common/bar. SSL Profile:/Common/clientssl.
    Dec 27 08:56:49 ve13a info tmm[17969]: Rule /Common/qux : GET / HTTP/1.1  User-Agent: curl/7.29.0  Host: 172.28.24.10  Accept: */*
    

    by the way, scan command returns number of conversions performed (not string that matches a conversion specifier). in short, combo variable should be after the scan command.

    e.g.

    scan [SSL::payload] {[0-9]{8}[0-9]{15}){1}} combo
    

    scan

    https://www.tcl.tk/man/tcl/TclCmd/scan.htm
    • bongshanks's avatar
      bongshanks
      Icon for Nimbostratus rankNimbostratus

      Ok, we are closer guys. Thanks so far. This is not an HTTPS transaction according to the application group I'm working with

      scan [SSL::payload] {[0-9]{8}[0-9]{15}){1}} combo
      

      Does scan perform the same search action as a regex?

      I've attached a screenshot of a log capture I ran on the LTM. If I run a regex against a log file, It does capture the 23 characters properly.

  • I'm trying to capture some client IP/SSL cipher information as well as a 23 character string of text that will be divided up into two identifiers.

    are the 23 chars in http request? if yes, isn't it easier to just use http_request event? ssl::payload is http request.

    e.g.

    // config
    
    root@(ve13a)(cfg-sync In Sync)(Active)(/Common)(tmos) list ltm virtual bar
    ltm virtual bar {
        destination 172.28.24.10:443
        ip-protocol tcp
        mask 255.255.255.255
        pool foo
        profiles {
            clientssl {
                context clientside
            }
            tcp { }
        }
        rules {
            qux
        }
        source 0.0.0.0/0
        source-address-translation {
            type automap
        }
        translate-address enabled
        translate-port enabled
        vs-index 4
    }
    root@(ve13a)(cfg-sync In Sync)(Active)(/Common)(tmos) list ltm rule qux
    ltm rule qux {
    when CLIENT_ACCEPTED {
      log local0. "SSL_CUSTOM: Connection of Client Source IP: [IP::client_addr]:[TCP::client_port]<-->[virtual name]<-->[LB::server]"
    }
    when CLIENTSSL_HANDSHAKE {
      if { [SSL::cipher bits] > 0 } then {
        log local0. "Client: [IP::client_addr] is using [SSL::cipher version]. SSL Cipher:[SSL::cipher name]. Virtual:[virtual]. SSL Profile:[PROFILE::clientssl name]."
        SSL::collect
      }
    }
    when CLIENTSSL_DATA {
      log local0. [SSL::payload]
      SSL::release
    }
    }
    
    // client
    
     curl -ik https://172.28.24.10
    HTTP/1.1 200 OK
    Date: Wed, 27 Dec 2017 01:06:34 GMT
    Server: Apache/2.2.3 (CentOS)
    Last-Modified: Fri, 15 Apr 2016 03:55:49 GMT
    ETag: "418e44-6a-fc825b40"
    Accept-Ranges: bytes
    Content-Length: 106
    Content-Type: text/html; charset=UTF-8
    
    
    
    
    
    
    This is 101 host.
    
    
    
    
    // log
    
    [root@ve13a:Active:In Sync] config  tail -f /var/log/ltm
    Dec 27 08:56:49 ve13a info tmm[17969]: Rule /Common/qux : SSL_CUSTOM: Connection of Client Source IP: 172.28.24.1:32806<-->/Common/bar<-->/Common/foo 0
    Dec 27 08:56:49 ve13a info tmm[17969]: Rule /Common/qux : Client: 172.28.24.1 is using TLSv1.2. SSL Cipher:ECDHE-RSA-AES128-GCM-SHA256. Virtual:/Common/bar. SSL Profile:/Common/clientssl.
    Dec 27 08:56:49 ve13a info tmm[17969]: Rule /Common/qux : GET / HTTP/1.1  User-Agent: curl/7.29.0  Host: 172.28.24.10  Accept: */*
    

    by the way, scan command returns number of conversions performed (not string that matches a conversion specifier). in short, combo variable should be after the scan command.

    e.g.

    scan [SSL::payload] {[0-9]{8}[0-9]{15}){1}} combo
    

    scan

    https://www.tcl.tk/man/tcl/TclCmd/scan.htm
    • bongshanks's avatar
      bongshanks
      Icon for Nimbostratus rankNimbostratus

      Ok, we are closer guys. Thanks so far. This is not an HTTPS transaction according to the application group I'm working with

      scan [SSL::payload] {[0-9]{8}[0-9]{15}){1}} combo
      

      Does scan perform the same search action as a regex?

      I've attached a screenshot of a log capture I ran on the LTM. If I run a regex against a log file, It does capture the 23 characters properly.

  • Does scan perform the same search action as a regex?

    can you try something like this?

    // config
    
    [root@ve13a:Active:In Sync] config  tmsh list ltm rule qux
    ltm rule qux {
    when CLIENT_ACCEPTED {
      log local0. "SSL_CUSTOM: Connection of Client Source IP: [IP::client_addr]:[TCP::client_port]<-->[virtual name]<-->[LB::server]"
    }
    when CLIENTSSL_HANDSHAKE {
      if { [SSL::cipher bits] > 0 } then {
        log local0. "Client: [IP::client_addr] is using [SSL::cipher version]. SSL Cipher:[SSL::cipher name]. Virtual:[virtual]. SSL Profile:[PROFILE::clientssl name]."
        SSL::collect
      }
    }
    when CLIENTSSL_DATA {
      log local0. "\[SSL::payload\] is [SSL::payload]"
      if { [regexp {(\d{8})(\d{15})} [SSL::payload] -> tid mid] } {
        log local0. "tid=$tid mid=$mid"
      }
      SSL::release
    }
    }
    
    // client
    
     (echo abc123xyz16021201334440212201602ijk987) |openssl s_client -connect 172.28.24.10:443 >& /dev/null
    
    // log
    
    [root@ve13a:Active:In Sync] config  tail -f /var/log/ltm
    Dec 27 11:24:53 ve13a info tmm[17969]: Rule /Common/qux : SSL_CUSTOM: Connection of Client Source IP: 172.28.24.1:32824<-->/Common/bar<-->/Common/foo 0
    Dec 27 11:24:53 ve13a info tmm[17969]: Rule /Common/qux : Client: 172.28.24.1 is using TLSv1.2. SSL Cipher:ECDHE-RSA-AES128-GCM-SHA256. Virtual:/Common/bar. SSL Profile:/Common/clientssl.
    Dec 27 11:24:53 ve13a info tmm[17969]: Rule /Common/qux : [SSL::payload] is abc123xyz16021201334440212201602ijk987
    Dec 27 11:24:53 ve13a info tmm[17969]: Rule /Common/qux : tid=16021201 mid=334440212201602
    
    • bongshanks's avatar
      bongshanks
      Icon for Nimbostratus rankNimbostratus

      I'll try that in the next change window in a week

      This is my first iteration that I wanted to try

      when CLIENTSSL_DATA {
      set payload [SSL::payload] 
      set combo ""
      set tid ""
      set mid ""
      regexp ([0-9]{8}[0-9]{15}){1} $payload combo 
      set tid [string range $combo 0 7]
      set mid [string range $combo 8 end]
      
  • Does scan perform the same search action as a regex?

    can you try something like this?

    // config
    
    [root@ve13a:Active:In Sync] config  tmsh list ltm rule qux
    ltm rule qux {
    when CLIENT_ACCEPTED {
      log local0. "SSL_CUSTOM: Connection of Client Source IP: [IP::client_addr]:[TCP::client_port]<-->[virtual name]<-->[LB::server]"
    }
    when CLIENTSSL_HANDSHAKE {
      if { [SSL::cipher bits] > 0 } then {
        log local0. "Client: [IP::client_addr] is using [SSL::cipher version]. SSL Cipher:[SSL::cipher name]. Virtual:[virtual]. SSL Profile:[PROFILE::clientssl name]."
        SSL::collect
      }
    }
    when CLIENTSSL_DATA {
      log local0. "\[SSL::payload\] is [SSL::payload]"
      if { [regexp {(\d{8})(\d{15})} [SSL::payload] -> tid mid] } {
        log local0. "tid=$tid mid=$mid"
      }
      SSL::release
    }
    }
    
    // client
    
     (echo abc123xyz16021201334440212201602ijk987) |openssl s_client -connect 172.28.24.10:443 >& /dev/null
    
    // log
    
    [root@ve13a:Active:In Sync] config  tail -f /var/log/ltm
    Dec 27 11:24:53 ve13a info tmm[17969]: Rule /Common/qux : SSL_CUSTOM: Connection of Client Source IP: 172.28.24.1:32824<-->/Common/bar<-->/Common/foo 0
    Dec 27 11:24:53 ve13a info tmm[17969]: Rule /Common/qux : Client: 172.28.24.1 is using TLSv1.2. SSL Cipher:ECDHE-RSA-AES128-GCM-SHA256. Virtual:/Common/bar. SSL Profile:/Common/clientssl.
    Dec 27 11:24:53 ve13a info tmm[17969]: Rule /Common/qux : [SSL::payload] is abc123xyz16021201334440212201602ijk987
    Dec 27 11:24:53 ve13a info tmm[17969]: Rule /Common/qux : tid=16021201 mid=334440212201602
    
    • bongshanks's avatar
      bongshanks
      Icon for Nimbostratus rankNimbostratus

      I'll try that in the next change window in a week

      This is my first iteration that I wanted to try

      when CLIENTSSL_DATA {
      set payload [SSL::payload] 
      set combo ""
      set tid ""
      set mid ""
      regexp ([0-9]{8}[0-9]{15}){1} $payload combo 
      set tid [string range $combo 0 7]
      set mid [string range $combo 8 end]
      
  • Nitass, that is a better way of doing it. I'm trying to clean it up a little, add HSL, set the logs to a few entries as possible, and add an else statement in case the transaction is missing the TID/MID.

     

    How is this?

     

  • when CLIENT_ACCEPTED {
    set hsl [HSL::open -proto UDP -pool hsl_syslog_pool]
    }
    when CLIENTSSL_HANDSHAKE {
    SSL::collect
    }
    }
    when CLIENTSSL_DATA {
    if { [regexp {(\d{8})(\d{15})} [SSL::payload] -> tid mid] } {
    HSL::send $hsl "Client: [IP::client_addr] is using [SSL::cipher version]. SSL Cipher:[SSL::cipher name]. Virtual:[virtual]. SSL Profile:[PROFILE::clientssl name]. tid=$tid mid=$mid."
    }
    SSL::release
    }
    }  else {
     If we did not have a TID OR MID in the transaction then just log the info that we have                   
    HSL::send $hsl "SSL_CUSTOM: No TID or MID TYPE found for Client: [IP::client_addr] is using [SSL::cipher version]. SSL Cipher:[SSL::cipher name]. Virtual:[virtual]. SSL Profile:[PROFILE::clientssl name]."
    }
    }
    
    • nitass's avatar
      nitass
      Icon for Employee rankEmployee

      you mean this one, don't you? if yes, it looks okay to me.

      when CLIENT_ACCEPTED {
        set hsl [HSL::open -proto UDP -pool hsl_syslog_pool]
      }
      when CLIENTSSL_HANDSHAKE {
        SSL::collect
      }
      when CLIENTSSL_DATA {
        if { [regexp {(\d{8})(\d{15})} [SSL::payload] -> tid mid] } {
          HSL::send $hsl "Client: [IP::client_addr] is using [SSL::cipher version]. SSL Cipher:[SSL::cipher name]. Virtual:[virtual]. SSL Profile:[PROFILE::clientssl name]. tid=$tid mid=$mid."
        } else {
           If we did not have a TID OR MID in the transaction then just log the info that we have                   
          HSL::send $hsl "SSL_CUSTOM: No TID or MID TYPE found for Client: [IP::client_addr] is using [SSL::cipher version]. SSL Cipher:[SSL::cipher name]. Virtual:[virtual]. SSL Profile:[PROFILE::clientssl name]."
        }
        SSL::release  
      }