Forum Discussion

Dale_Cooke_1773's avatar
Dale_Cooke_1773
Icon for Nimbostratus rankNimbostratus
Nov 19, 2015

SSL Cipher (reporting, graphing, logging)

We are in the process of disabling weaker Cipher strengths on our https servers, I wondered if anyone has any experience of getting the F5 to log and report on the Cipher strength that each browser session negotiates? The idea would be to report on the amount of users connecting with weaker cipher strengths so we can understand how many people we might affect if we disabled a specific cipher. At the moment the SSL handshake is passed through the F5 and done directly on the server, but I'm open to the idea of moving the SSL negotiate on to the VIP (F5) if it would give this level of visibility.

 

9 Replies

  • We've had a requirement to do this as well, we offload SSL to the LTM device and then apply the following iRule, it logs to the LTM log which we ship off to syslog into a separate file.

     

    when LB_SELECTED { log -noname local0. "SSL Cipher [SSL::cipher name] selected by client [IP::remote_addr] for pool [LB::server pool]" }

     

  • I have a slightly more verbose iRule for this.

    when HTTP_REQUEST {
    
        if { [info exists logged] && $logged == 1 }{
             Do nothing. Already logged for this connection
        } else {
            set logged 1
            log "Rule CIPHER_logging fired, from [IP::remote_addr] to vip [IP::local_addr] Cipher [SSL::cipher name]:[SSL::cipher version]:[SSL::cipher bits] Client:[HTTP::header "User-Agent"]:[HTTP::host]"
        }
    }
    
  • The SSL:: commands only work if you process the SSL at the F5. If you're passing SSL traffic through, you have to get a little deeper in the weeds. Here's a very crude example of what it might look like to sniff the negotiated cipher from the server's ServerHello message:

    when CLIENT_ACCEPTED {
         store client IP
        set clientip [IP::client_addr]
    }
    when SERVER_CONNECTED {
         collecting server side responses
        TCP::collect
    }
    when SERVER_DATA {
         sniffing the packet type
        binary scan [TCP::payload] cSSc type len ver hs
         22 = SSL handshake, 2 = ServerHello 
        if { ( $type == 22 ) and ( $hs == 2 ) } {
            binary scan [TCP::payload] H86H2 sh sidlen
            if { $sidlen ne "00" } {
                 if sidlen not 00 (session ID length), skip past ID and collect cipher
                scan $sidlen %x dec
                set dec [expr $dec * 2]
                binary scan [TCP::payload] H88H${dec}H4 sh sid cipher
                log local0. "Client: $clientip negotiated cipher: $cipher"
            } else {
                 no session ID, collect cipher
                binary scan [TCP::payload] H88H4 sh cipher
                log local0. "Client: $clientip negotiated cipher: $cipher"
            }
        }
        TCP::release
    }
    

    Again, stressing very crude example. The log will show something like this:

    Client: 10.70.0.51 negotiated cipher: c030
    

    The "c030" here is the hexadecimal value of the cipher version, as defined here:

    http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml

    So c030 = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"

  • All very useful answers, thanks very much for everyone's input. Just got to decide weather to move the SSL to the F5 or not now..

     

    Thanks again

     

    • Brad_Parker's avatar
      Brad_Parker
      Icon for Cirrus rankCirrus
      Even if you want to still have SSL to the server you would get a lot of benefit by doing SSL bridging by using a client and server SSL profile to decrypt and then re-encrypt to the server. Lots of benefits to this and it is transparent to the server. I would highly recommend performing SSL termination on your LTM. You will not regret it.
  • @Kevin Stewart I tried to use the rule which you mentioned. I was unable to get the content type as 22 in the payload. Not sure why. I extracted all the bytes from the payload nothing made sense to me. Here is what it logs: Type == 72 84 84 80 47 49 46 49 32 50 48 ..... 125 125

     

    Here is the part of the rule modified:

     

    when SERVER_DATA {

     

    binary scan [TCP::payload] c* type log local0. "Type == $type "

     

    • Kevin_Stewart's avatar
      Kevin_Stewart
      Icon for Employee rankEmployee

      Well,

       

      • c* would give you all of the bytes, and you only need the first one

         

      • 72 probably indicate that you're not looking at part of the TLS handshake. In fact, if you decode that hex string, it starts with „„€"GIFI2PH", which looks like (I'm assuming) a plaintext image response.

         

    • rshetty_242152's avatar
      rshetty_242152
      Icon for Nimbostratus rankNimbostratus

      I used the rule which you posted. It never logged anything since the condition was not satisfied for 22 and 2 so i logged the values of type and hs in "binary scan [TCP::payload] cSSc type len ver hs".

       

      The logs showed the following Rule /Common/cipher_used_hsl : Type == 72 || hs == 49

       

      Since the number 72 and 49 were not what was expected i decided to get the entire list of payload to see what is going on, hence i ended up using c*.

       

      I tried this rule on couple of different urls. All send the same initial strings.

       

    • Kevin_Stewart's avatar
      Kevin_Stewart
      Icon for Employee rankEmployee

      Right, but the iRule can't work if the traffic isn't encrypted.