
Collecting NetScaler LOGs in Elasticsearch and Visualizing Them in Grafana
Today we have a pretty interesting menu, and if you are in charge of a NetScaler in your infrastructure, in this post we will see how we can collect their logs to later be processed and finally make a dashboard in Grafana that shows in real time (or historical) The data collected.
So what I said, we can have our Citrix NetScaler send its logs to Logstash to be processed and separated into structured data what are lines from different logs. We'll store this information in an Elasticsearch index and then with a connector or 'Data Source'’ of Grafana we will be able to access this data, to view them in real time or in a certain period of time (Last 24h, month…). And everyone can make the dashboard based on the role played by their NS, if you have the Gateway service seeing the public IPs that access, Traffics… If we have a Content Switching ditto in addition to destinations… If we have a Load Balancing, then really analyze where the connections go… in the end, everything that is stored in a log can be exploited and NetScaler is a very interesting device to know what happens inside, such as the display of authentications, correct or incorrect.
First we obviously have to have the Elastic Stack part installed, What has been Logstash, Elasticsearch and Kibana; then it would be to instruct our NetScaler to send the Logs to Logstash, to the port of our choice, We'll invent one (since “System” > “Auditing” > “Syslog Auditing”. Remember to save the configuration to the NetScaler.
The next thing will be to create a file in Logstash that you will need to ingest, Transform and send data. Primero escuchar en el puerto UDP indicado en el paso anterior; second, tratar los logs que recibe y separarlos en distintos campos para ser por último almacenados en nuestro Elasticsearch.
Input { UDP { type => "Netscaler" port => "1517" tags => ["Netscaler"] } } filter { if [type] == "Netscaler" { Grok { match => { "Message" => [ "^<%{POSINT:syslog_pri}>%{SPACE}%{DATE_US:Log_fecha}:%{TIME:Log_hora}%{SPACE}%{SYSLOGHOST:NSlog_hostname}%{SPACE}0-PPE-0%{SPACE}:%{SPACE}default%{SPACE}%{WORD:Log_tipo}%{SPACE}%{WORD:Log_evento}%{SPACE}%{INT:Log_id}%{SPACE}0%{SPACE}:%{SPACE}Context%{SPACE}%{USERNAME:User}@%{IPV4:IP_origen}%{SPACE}-%{SPACE}SessionId:%{SPACE}%{INT:Session_id}%{SPACE}-%{SPACE}User%{SPACE}%{USERNAME:Usuario2}%{SPACE}-%{SPACE}Client_ip%{SPACE}%{IPV4:IP_origen2}%{SPACE}-%{SPACE}Nat_ip%{SPACE}\"Mapped Ip"%{SPACE}-%{SPACE}Vserver%{SPACE}%{IPV4:vServer_ip}:%{NUMBER:vServer_puerto}%{SPACE}-%{SPACE}Start_time%{SPACE}\"%{DATE_US:Inicio_fecha}:%{TIME:Inicio_hora}%{SPACE}\"%{SPACE}-%{SPACE}End_time%{SPACE}\"%{DATE_US:Fin_fecha}:%{TIME:Fin_hora}%{SPACE}\"%{SPACE}-%{SPACE}Duration%{SPACE}%{TIME:Duracion}%{SPACE}-%{SPACE}Http_resources_accessed%{SPACE}%{NUMBER:Http_resources_accessed}%{SPACE}-%{SPACE}NonHttp_services_accessed%{SPACE}%{NUMBER:NonHttp_services_accessed}%{SPACE}-%{SPACE}Total_TCP_connections%{SPACE}%{NUMBER:Total_TCP_connections}%{SPACE}-%{SPACE}Total_UDP_flows%{SPACE}%{NUMBER:otal_UDP_flows}%{SPACE}-%{SPACE}Total_policies_allowed%{SPACE}%{NUMBER:Total_policies_allowed}%{SPACE}-%{SPACE}Total_policies_denied%{SPACE}%{NUMBER:Total_policies_denied}%{SPACE}-%{SPACE}Total_bytes_send%{SPACE}%{NUMBER:Total_bytes_send}%{SPACE}-%{SPACE}Total_bytes_recv%{SPACE}%{NUMBER:Total_bytes_recv}%{SPACE}-%{SPACE}Total_compressedbytes_send%{SPACE}%{NUMBER:Total_compressedbytes_send}%{SPACE}-%{SPACE}Total_compressedbytes_recv%{SPACE}%{NUMBER:Total_compressedbytes_recv}%{SPACE}-%{SPACE}Compression_ratio_send%{SPACE}%{NUMBER:Compression_ratio_send}\%%{SPACE}-%{SPACE}Compression_ratio_recv%{SPACE}%{NUMBER:Compression_ratio_recv}\%%{SPACE}-%{SPACE}LogoutMethod%{SPACE}\"%{DATE:LogoutMethod}\"%{SPACE}-%{SPACE}Group(s)%{SPACE}\"%{DATE:Group}\"", "^<%{POSINT:syslog_pri}>%{SPACE}%{DATE_US:Log_fecha}:%{TIME:Log_hora}%{SPACE}%{SYSLOGHOST:NSlog_hostname}%{SPACE}0-PPE-0%{SPACE}:%{SPACE}default%{SPACE}%{WORD:Log_tipo}%{SPACE}%{WORD:Log_evento}%{SPACE}%{INT:Log_id}%{SPACE}0%{SPACE}:%{SPACE}Context%{SPACE}%{USERNAME:User}@%{IPV4:IP_origen}%{SPACE}-%{SPACE}SessionId:%{SPACE}%{INT:Session_id}%{SPACE}-%{SPACE}User%{SPACE}%{USERNAME:Usuario2}%{SPACE}-%{SPACE}Client_ip%{SPACE}%{IPV4:IP_origen2}%{SPACE}-%{SPACE}Nat_ip%{SPACE}\"Mapped Ip"%{SPACE}-%{SPACE}Vserver%{SPACE}%{IPV4:vServer_ip}:%{NUMBER:vServer_puerto}%{SPACE}-%{SPACE}%{GREEDYDATA:Message}", "^<%{POSINT:syslog_pri}>%{SPACE}%{DATE_US:Log_fecha}:%{TIME:Log_hora}%{SPACE}%{SYSLOGHOST:NSlog_hostname}%{SPACE}0-PPE-0%{SPACE}:%{SPACE}default%{SPACE}%{WORD:Log_tipo}%{SPACE}%{WORD:Log_evento}%{SPACE}%{INT:Log_id}%{SPACE}0%{SPACE}:%{SPACE}User%{SPACE}%{USERNAME:User}%{SPACE}-%{SPACE}Client_ip%{SPACE}%{IPV4:IP_origen}%{SPACE}-%{SPACE}%{GREEDYDATA:Message}", "^<%{POSINT:syslog_pri}>%{SPACE}%{DATE_US:Log_fecha}:%{TIME:Log_hora}%{SPACE}%{SYSLOGHOST:NSlog_hostname}%{SPACE}0-PPE-0%{SPACE}:%{SPACE}default%{SPACE}%{WORD:Log_tipo}%{SPACE}%{WORD:Log_evento}%{SPACE}%{INT:Log_id}%{SPACE}0%{SPACE}:%{SPACE}Source%{SPACE}%{IPV4:IP_origen}:%{NUMBER:Puerto_origen}%{SPACE}-%{SPACE}Vserver%{SPACE}%{IPV4:vServer_ip}:%{NUMBER:vServer_puerto}%{SPACE}-%{SPACE}NatIP%{SPACE}%{IPV4:NAT_ip}:%{NUMBER:NAT_puerto}%{SPACE}-%{SPACE}Destination%{SPACE}%{IPV4:IP_destino}:%{NUMBER:Puerto_destino}%{SPACE}-%{SPACE}Delink%{SPACE}Time%{SPACE}%{DATE_US:Delink_fecha}:%{TIME:Delink_hora}%{SPACE}-%{SPACE}Total_bytes_send%{SPACE}%{INT:Total_bytes_enviados}%{SPACE}-%{SPACE}Total_bytes_recv%{SPACE}%{INT:Total_bytes_recibidos}", "^<%{POSINT:syslog_pri}>%{SPACE}%{DATE_US:Log_fecha}:%{TIME:Log_hora}%{SPACE}%{SYSLOGHOST:NSlog_hostname}%{SPACE}0-PPE-0%{SPACE}:%{SPACE}default%{SPACE}%{WORD:Log_tipo}%{SPACE}%{WORD:Log_evento}%{SPACE}%{INT:Log_id}%{SPACE}0%{SPACE}:%{SPACE}Source%{SPACE}%{IPV4:IP_origen}:%{NUMBER:Puerto_origen}%{SPACE}-%{SPACE}Destination%{SPACE}%{IPV4:Destino_ip}:%{NUMBER:Destino_puerto}%{SPACE}-%{SPACE}Start%{SPACE}Time%{SPACE}%{DATE_US:Inicio_fecha}:%{TIME:Inicio_hora}%{SPACE}-%{SPACE}End%{SPACE}Time%{SPACE}%{DATE_US:Fin_fecha}:%{TIME:Fin_hora}%{SPACE}-%{SPACE}Total_bytes_send%{SPACE}%{INT:Total_bytes_enviados}%{SPACE}-%{SPACE}Total_bytes_recv%{SPACE}%{INT:Total_bytes_recibidos}", "^<%{POSINT:syslog_pri}>%{SPACE}%{DATE_US:Log_fecha}:%{TIME:Log_hora}%{SPACE}%{SYSLOGHOST:NSlog_hostname}%{SPACE}0-PPE-0%{SPACE}:%{SPACE}default%{SPACE}%{WORD:Log_tipo}%{SPACE}%{WORD:Log_evento}%{SPACE}%{INT:Log_id}%{SPACE}0%{SPACE}:%{SPACE}Source%{SPACE}%{IPV4:IP_origen}:%{NUMBER:Puerto_origen}%{SPACE}-%{SPACE}Vserver%{SPACE}%{IPV4:vServer_ip}:%{NUMBER:vServer_puerto}%{SPACE}-%{SPACE}NatIP%{SPACE}%{IPV4:NAT_ip}:%{NUMBER:NAT_puerto}%{SPACE}-%{SPACE}Destination%{SPACE}%{IPV4:IP_destino}:%{NUMBER:Puerto_destino}%{SPACE}-%{SPACE}Delink%{SPACE}Time%{SPACE}%{DATE_US:Delink_fecha}:%{TIME:Delink_hora}%{SPACE}Total_bytes_send%{SPACE}%{INT:Total_bytes_enviados}%{SPACE}-%{SPACE}Total_bytes_recv%{SPACE}%{INT:Total_bytes_recibidos}", "^<%{POSINT:syslog_pri}>%{SPACE}%{DATE_US:Log_fecha}:%{TIME:Log_hora}%{SPACE}%{SYSLOGHOST:NSlog_hostname}%{SPACE}0-PPE-0%{SPACE}:%{SPACE}default%{SPACE}%{WORD:Log_tipo}%{SPACE}%{WORD:Log_evento}%{SPACE}%{INT:Log_id}%{SPACE}0%{SPACE}:%{SPACE}SPCBId%{SPACE}%{INT:SPCBId}%{SPACE}-%{SPACE}ClientIP%{SPACE}%{IPV4:IP_origen}%{SPACE}-%{SPACE}ClientPort%{SPACE}%{NUMBER:Puerto_origen}%{SPACE}-%{SPACE}VserverServiceIP%{SPACE}%{IPV4:vServer_ip}%{SPACE}-%{SPACE}VserverServicePort%{SPACE}%{NUMBER:vServer_puerto}%{SPACE}-%{SPACE}ClientVersion%{SPACE}%{DATE:Client_version}%{SPACE}-%{SPACE}CipherSuite%{SPACE}\"%{DATE:Cipher_suite}\"(%{SPACE}-%{SPACE}Session%{SPACE}Reuse%{SPACE}-%{SPACE}HandshakeTime%{SPACE}%{INT:Handshake_time}%{SPACE}ms)?", "^<%{POSINT:syslog_pri}>%{SPACE}%{DATE_US:Log_fecha}:%{TIME:Log_hora}%{SPACE}%{SYSLOGHOST:NSlog_hostname}%{SPACE}0-PPE-0%{SPACE}:%{SPACE}default%{SPACE}%{WORD:Log_tipo}%{SPACE}%{WORD:Log_evento}%{SPACE}%{INT:Log_id}%{SPACE}0%{SPACE}:%{SPACE}SPCBId%{SPACE}%{INT:SPCBId}%{SPACE}-%{SPACE}IssuerName%{SPACE}\"%{SPACE}%{DATE:Issuer_name}\"", "^<%{POSINT:syslog_pri}>%{SPACE}%{DATE_US:Log_fecha}:%{TIME:Log_hora}%{SPACE}%{SYSLOGHOST:NSlog_hostname}%{SPACE}0-PPE-0%{SPACE}:%{SPACE}default%{SPACE}%{WORD:Log_tipo}%{SPACE}%{WORD:Log_evento}%{SPACE}%{INT:Log_id}%{SPACE}0%{SPACE}:%{SPACE}SPCBId%{SPACE}%{INT:SPCBId}%{SPACE}-%{SPACE}SubjectName%{SPACE}\"%{SPACE}%{DATE:Subject_name}\"", "^<%{POSINT:syslog_pri}>%{SPACE}%{DATE_US:Log_fecha}:%{TIME:Log_hora}%{SPACE}%{SYSLOGHOST:NSlog_hostname}%{SPACE}0-PPE-0%{SPACE}:%{SPACE}default%{SPACE}%{WORD:Log_tipo}%{SPACE}%{WORD:Log_evento}%{SPACE}%{INT:Log_id}%{SPACE}0%{SPACE}:%{SPACE}Context%{SPACE}%{USERNAME:User}@%{IPV4:IP_origen}%{SPACE}-%{SPACE}SessionId:%{SPACE}%{INT:Session_id}%{SPACE}-%{SPACE}%{HOSTNAME:FQDN}%{SPACE}User%{SPACE}%{USERNAME:Usuario2}%{SPACE}:%{SPACE}Group(s)%{SPACE}%{DATE:Group}%{SPACE}:%{SPACE}Vserver%{SPACE}%{IPV4:vServer_ip}:%{NUMBER:vServer_puerto}%{SPACE}-%{SPACE}%{DATE_US:Date}:%{TIME:Hour}%{SPACE}:%{SPACE}%{GREEDYDATA:Message}", "^<%{POSINT:syslog_pri}>%{SPACE}%{DATE_US:Log_fecha}:%{TIME:Log_hora}%{SPACE}%{SYSLOGHOST:NSlog_hostname}%{SPACE}0-PPE-0%{SPACE}:%{SPACE}default%{SPACE}%{WORD:Log_tipo}%{SPACE}%{WORD:Log_evento}%{SPACE}%{INT:Log_id}%{SPACE}0%{SPACE}:%{SPACE}%{GREEDYDATA:Message}" ] } } Geoip { source => "IP_origen" target => "Geoip" add_field => [ "[Geoip][Coordinates]", "%{[Geoip][Longitude]}" ] add_field => [ "[Geoip][Coordinates]", "%{[Geoip][Latitude]}" ] } Mute { convert => [ "[Geoip][Coordinates]", "float" ] convert => [ "Total_bytes_enviados", "Integer" ] convert => [ "Total_bytes_recibidos", "Integer" ] } } } output { if ([type]=="Netscaler"){ ElasticSearch { index => "netscaler-%{+YYYY. MM.dd}" hosts=> "DIRECCION_IP_ELASTICSEARCH:9200" } } }
So let's create for example the following configuration file '/etc/logstash/conf.d/netscaler.conf', I leave you my example below. My filters are very basic and first of Logstash, but they work 😉 so if you are interested you can copy them, and if you improve them you pass 🙂 them to me At the end we will indicate in the output the Elasticsearch server where to send the data and the index where it will be stored; Remember that if you have authentication put the 'username' parameters’ & 'password’ in the output. The truth is that I am looking at the code now and it can be improved, I scratched myself with the spaces I remember… I hope you can forgive me but it works, at least with the latest versions such as NetScaler 13.0.
Once the configuration file has been created, remember to restart the Logstash service to reload. Afterwards as always, we will go to Kibana and once the data is coming in we can go to “Management” > “Stack management” > “Kibana” > “Index Patterns” > “Create index pattern” To create the index pattern, As I said, as usual (in this case and without the quotation marks) 'netscaler-*’ and we will have the data already stored in Elasticsearch correctly. Now we could connect from “Discover” to our NetScaler index and visualize that it is collecting data.
And then, after creating the index in Kibana, now in our Grafana we should create a “Data Source” that targets our Elasticsearch and the NetScaler index. Then it's letting your imagination run wild, make a Dashboard with different Dashboards, with different data to visualize, one World Map with incoming connections, One of Style Sankey to view origin/destination IPs and traffic being sent, in column format, in stalemate to view specific data for example the correct logins, Incorrect, The connections…
Everything can be used for you to take ideas and improve them, With this you will be able to see what happens in our(s) Citrix NetScaler Real-Time, Putting an automatic refresh every 10 seconds is very impressive, It will also help us to analyze the summary of a day, or knowing when something strange happens… As usual, Thank you all and more to those who move this type of content on social 😉 networks