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  
      }