There is something I frequently get asked for: How can we find out, which users use which ciphers? Will Citrix ADC show this information? Does ADM show it?
A simple answer would be: No chance, ADC can’t do it at all. ADM – however – can do. If you don’t like ADM (I’d wonder why) you can’t.
Let’s not make things that simple. We all are engineers. The word comes from the Latin word ingenium. It has the same roots as “genius”. So in every engineer, there is a little bit of a genius as well!
The fact is: Citrix ADC has counters to tell us, how much traffic or connection use which SSL/TLS versions. So we can find, there is 2 % SSL v3, 8 % TLS 1.0, 2 % TLS 1.1., 39 % TLS 1.2, and 49 % TLS 1.3. But that’s just a starting point to our question, not the answer. The implicit question of my customer, of course, had been: Who – the hell – is still using SSL v.3? And who – the f*** – is still using TLS 1.0 or TLS 1.1 (and keeps us from removing these outdated versions)?
So how can we find out? Is it in syslog? No. Nothing like that!
Wait!
We have these user-configurable log messages. Why don’t we use them to send the desired information to Syslog? I have already written about user-configurable log messages. Don’t forget to enable user-configurable log messages in your Syslog settings, or the trick won’t work!
Logging data from unauthenticated SSL sessions
It’s obvious, we can’t find out, who the actual user is, because we did not authenticate it. But we can log connections and IPs, this would help by a little bit. The logging message could be something like that:
add audit messageaction log_SSL_params NOTICE "\"SSL-Params for \" + CLIENT.IP.SRC + \" is using TLS 1.\" +( CLIENT.SSL.VERSION.TYPECAST_NUM_AT - 769) + \" with \" + CLIENT.SSL.CIPHER_NAME"
I have set the severity of this log to NOTICE (I guess, that’s what it is: a notice). The text contains the client IP, the TLS version, and the exact cipher this client used. CLIENT.SSL.VERSION
, unfortunately, returns strange numbers. This little bit of mathematic gives us the correct values. Of course, you could also append something like HTTP.REQ.HEADER ("User-Agent")
, to find out which browser this user used.
If you see TLS 1.9 or 1.-9, it would in fact be SSL v3 (I had no chance to emulate an SSL v3 connection, as none of my browsers is supporting SSL v3 anymore.
The policy is a simple rewriting policy. Nothing special about it. Type is NOREWRITE, and I bound the logging policy to it.
Maybe, you wonder why I am using this policy expression? I don’t want to get too many log entries per user, so I decided not to log images, style sheets, java scripts, and things like that. Of course, it’s up to you to do find a different expression if you prefer. If you scroll down just a little bit, you would see a way more skillful approach to log as little data as possible.
The log would look like that:
For mathematical reasons, this may also log TLS 1.9 (or TLS 1.-9 or whatever), which would in fact be SSL v3.
A more skillful policy expression?
I thought of logging even fewer data. How can I do? I thought of using variables and write IP/SSL-version pairs into it. If the IP/SSL-Version pair is in my list, I would not log it. That’s a highly complex setup. I didn’t sleep well last night, but I wanted to solve this problem (stupid me, to be honest. Maybe it’s a sportive approach to solve every problem, but no doubt: stupid). But I woke up in the middle of the night with a solution in my hands. Ther is a feature built into Citrix ADC / NetScaler that can do exactly that. Did you guess which? Exactly! It’s the rate-limiting feature! So all I had to do is creating a limit selector and a limit identifier and use these.
Limit selector
add stream selector ssl-ciphers_per_IP CLIENT.IP.SRC CLIENT.SSL.VERSION
This stream selector selects pairs of IP and SSL-Version. Maybe CLIENT.SSL.CIPHER_NAME
would be even better, more precise, but way more costly in terms of RAM than a 3 digits number.
The Limit Identifier
add ns limitIdentifier is_client_logged -timeSlice 900000 -selectorName ssl-ciphers_per_IP
We use our previously created Limit Selector, set the Threshold to 1, and a Time Slice to a proper value. This is the time, a record will live within the table. 900,000 ms is 900 seconds or 15 minutes. So we permit only one log per user within 15 minutes. The higher the Time Slice, the more memory is wasted on storing the table. The lower it is, the more log entries you will get.
The policy expression
Now we have a list of users not to be logged, so we need to use it in our policy. That’s the improved policy:
add rewrite policy rw_pol_dontdoit "SYS.CHECK_LIMIT(\"is_client_logged\").NOT" NOREWRITE -logAction log_SSL_params
This policy expression uses the previously created rate limit identifier to not log clients on the Syslog. In other words: If you request data for the first time, you trigger the policy (you are not on the list), but at the same time, add yourself to the list. With your subsequent requests, you can be found on the list and – therefore – won’t trigger the policy.
Problem solved!
Logging data about authenticated SSL sessions
Of course, we could also log the user name, however, we need to know its name. So logging a user name can only be done with authenticated users. But if users are authenticated, we are able to add information about the user name as well.
add audit messageaction log_SSL_params NOTICE "\"SSL-Params for \" + AAA.USER.NAME + \" (\" + CLIENT.IP.SRC + \") is using TLS 1.\" +( CLIENT.SSL.VERSION.TYPECAST_NUM_AT - 769) + \" with \" + CLIENT.SSL.CIPHER_NAME "
Different from the previous version, I also log AAA.USER.NAME into the Syslog. That way, we know, where the user came from (using the IP address) and who it was.
That’s the output from Syslog.
As always, I would like to know what you think about my blog, I would like to hear about your concerns and get suggestions. Just drop a short message into the comments section!
Have fun
Johannes