Author: Jarek

Wireshark MATE for Diameter Charging-Control

That’s surprising that for all these years I didn’t know about Wireshark MATE:

MATE: Meta Analysis and Tracing Engine

What is MATE? Well, to keep it very short, with MATE you can create user configurable extension(s) of the display filter engine.

MATE creates a filterable tree based on information contained in frames that share some relationship with information obtained from other frames. The way this relationships are made is described in a configuration file. The configuration file tells MATE what makes a PDU and how to relate it to other PDUs.

I found it very useful when analysing Diameter logs. It helps to solve eternal problem: how to get whole diameter session when you know only MSISDN (or Result-Code or an other AVP which is not present in both CCR and CCA and the only way to bind CCR and CCA is Session-Id).

The answer is MATE. 

If I want to search for my MSISDN, I can use this filter:

mate.diam_transaction.msisdn == "46702904828"

In result, Wireshark will filter all CCR and CCAs where this subscriber is involved:

Mate in action

How to configure Wireshark for Diameter with MATE?

Lucky, MATE is built-in into current version of Wireshark. All we need to do is to create configuration and set it up in Wireshark preferences

MATE cfg file for Diameter

As I wanted to filter using MSISDN (actually Subscription-Id) and Result-Code, both needs to be extracted.

We will be binding messages using Session-Id, App Id and End-to-end Identifier

(credits needs to go to an anonymous poster to Wireshark forum; I’ve modified this file slightly adding MSISDN and Stop conditions)

// Create a "diam_pdu" that contains various pieces of the processed Diameter
// message.
Pdu diam_pdu Proto diameter Transport ip {
Extract command_code From diameter.cmd.code;
Extract app_id From diameter.applicationId;
Extract session_id From diameter.Session-Id;
Extract e2eid From diameter.endtoendid;
Extract resultcode From diameter.Result-Code;
Extract msisdn From diameter.Subscription-Id-Data;
Extract flag From diameter.flags.request;
Extract request_type From diameter.CC-Request-Type;
};

// Then create a GOP (Group Of Pdus) where the each GOP contains all the PDUs
// (msgs) that whose command_code, app_id, session_id, and e2eid match.
Gop diam_transaction On diam_pdu Match (command_code, app_id, session_id, e2eid) {
Start();
Stop(flag=0,request_type=3);

// Store the result code in the GOP
Extra(resultcode, msisdn);
};

Done;

Save the file somewhere on the disk.

Configure Wireshark

Wireshark protocols configuration set this file under MATE:

Now a new protocol tree MATE should appear in each Diameter Packet details. You can use these pseudo-AVPs for filtering.

How to enable R environment in Golden Cheetah on Mac?

Somehow I couldn’t find a complete guide how to install R and configure it properly in Golden Cheetah (I’m using v3.5).

There is a good guide how to work with R in GC, but actually – no description how to enable it.

1. Download R for MacOS

I got it from https://cran.r-project.org/bin/macosx/ page

(I’ve also installed R Studio but it seems not really needed)

2. Check where R home is located

In terminal, start R and check the home:

It’s /Library/Frameworks/R.framework/Resources in my environment.

3. In GC open Preferences and set the same in R Installation Directory

Wireshark LUA plugin

This is an example of a LUA plugin for Wireshark which goes through the packets and generates a statistic.

In my case, I was looking for Diameter Charging-Control stats around Reporting-Reason Valdity-Time.

The project is hosted in GitHub.

Pre-requisites

  • Wireshark
  • LUA environment

I’ve tested it on MacOS, same should work in Linux without modifications. I’m not sure about Windows – I will appreciate you comments.

How to start

The plugin can be started in two ways:

Command-line

Update start.sh to provide:

  • path to your Wireshark application
  • name to your pcap / snoop file
TSHARK='/Users/jhartman/Tools/Internet/Wireshark/Wireshark.app/Contents/MacOS/tshark'
INPUT='/Users/jhartman/Documents/Documents/Oracle/Telia/!Local/Logs and config/Diameter/!Production/spikes - 2020-02-03/dgw-spikes-tr001prdgw11.snoop'

Then you can invoke start.sh and see the result:

MBP:wiresharkLUA jhartman$ ./start.sh
Starting in command-line mode
Registering Listener
QUOTA_EXHAUSTED (3)            - 359 		(7.701 %)
FINAL (2)                      - 402 		(8.623 %)
VALIDITY_TIME (4)              - 3634 		(77.949 %)
QHT (1)                        - 267 		(5.727 %)

Total                          - 4662 		(100 %)

USU (octets) when VALIDITY_TIME (4)
Median  : 292458 octets, 285.60 kB
Average : 19140604 octets, 18692.00 kB
Min     : 112 octets
Max     : 310552054 octets, 303273.49 kB

Histogram of USU (Validity-Time)
 1:         0 MB -        11 MB :   2691 (74.05 %)
 2:        11 MB -        23 MB :    306 (8.42 %)
 3:        23 MB -        35 MB :    131 (3.60 %)
 4:        35 MB -        47 MB :     84 (2.31 %)
 5:        47 MB -        59 MB :     61 (1.68 %)
 6:        59 MB -        71 MB :     60 (1.65 %)
 7:        71 MB -        82 MB :     43 (1.18 %)
 8:        82 MB -        94 MB :     41 (1.13 %)
 9:        94 MB -       106 MB :     26 (0.72 %)
10:       106 MB -       118 MB :     24 (0.66 %)
11:       118 MB -       130 MB :     21 (0.58 %)
12:       130 MB -       142 MB :     15 (0.41 %)
13:       142 MB -       154 MB :     13 (0.36 %)
14:       154 MB -       165 MB :     16 (0.44 %)
15:       165 MB -       177 MB :     12 (0.33 %)
16:       177 MB -       189 MB :     11 (0.30 %)
17:       189 MB -       201 MB :     15 (0.41 %)
18:       201 MB -       213 MB :     10 (0.28 %)
19:       213 MB -       225 MB :      7 (0.19 %)
20:       225 MB -       236 MB :     10 (0.28 %)
21:       236 MB -       248 MB :      6 (0.17 %)
22:       248 MB -       260 MB :      9 (0.25 %)
23:       260 MB -       272 MB :      9 (0.25 %)
24:       272 MB -       284 MB :      8 (0.22 %)
25:       284 MB -       296 MB :      5 (0.14 %)
QUOTA_EXHAUSTED (3)            - 359 		(7.701 %)
FINAL (2)                      - 402 		(8.623 %)
VALIDITY_TIME (4)              - 3634 		(77.949 %)
QHT (1)                        - 267 		(5.727 %)

Total                          - 4662 		(100 %)

Note If you can see two invocations of LUA plugin, see the note in Wireshark GUI section:

Starting in command-line mode
Registering Listener
Starting in command-line mode
Registering Listener

Wireshark GUI

In order to invoke the plugin from the GUI, you need to install it (i.e. upload) into relevant folder which is ‘ (see Wireshark Plugin folders).

As I’m working with GitHub, I prefer to make a sym-link:

MBP:wiresharkLUA jhartman$ cd ../wiresharkLUA
MBP:wiresharkLUA jhartman$ ln -s $(pwd)/reportingReason-gui.lua ~/.local/lib/wireshark/plugins/reportingReason-gui.lua

After making the link, you need to reload the plugins by selecting Analyse -> Reload LUA plugins

Reload

Then you can open a Diameter Charging-Control log (i.e. one defined as per RFC 4006 or a relevant 3GPP spec) and start the analyze:

Reload

After a while, a window with statistics results will pop up: Reload

Wireshark LUA script starts twice when invoked from commandline

You may see that the script is invoked twice when starting from commandline:

MBP:wiresharkLUA jhartman$ ./start.sh
Starting in command-line mode
Registering Listener
Starting in command-line mode
Registering Listener
...
...

Reason for this the way how tshark loads the plugins:

  • first time it loads all user plugins from ~/.local/lib/wireshark/plugins/
  • and then it loads and executes all plugins defined through -X, i.e. -X lua_script:reportingReason-gui.lua

Solution: remove the plugin from the user plugins:

MBP:wiresharkLUA jhartman$ rm ~/.local/lib/wireshark/plugins/reportingReason-gui.lua

Withings to Garmin tool going beyond! TrainerRoad syncing

As I’m user of cycling training platform TrainerRoad, the tool has been expanded to support weight synchronisation to TrainerRoad profile.

To use, specify Trainer Road user and passwords as shown below:

Usage

Usage: sync.py [options]

Options:
  -h, --help            show this help message and exit
  --garmin-username=<user>, --gu=<user>
                        username to login Garmin Connect.
  --garmin-password=<pass>, --gp=<pass>
                        password to login Garmin Connect.
  --trainerroad-username=<user>, --tu=<user>
                        username to login TrainerRoad.
  --trainerroad-password=<user>, --tp=<user>
                        username to login TrainerRoad.
  -f <date>, --fromdate=<date>
  -t <date>, --todate=<date>
  --no-upload           Won't upload to Garmin Connect and output binary-
                        strings to stdout.
  -v, --verbose         Run verbosely

As always – for download, best go to GitHub

OUI issue NGINST-64002: Error occurred in validation of: “Host Name”

When installing an Oracle application using OUI (Oracle Universal Installer) sometimes it verifies if a given host is reachable. 

Unfortunately, in my case, it was always failing:

All this despite the host was perfectly reachable using Ping:

So what was happening? The OUI is using under the hood Java’s InetAddress.isReachable(). The algorithm is:

  1.  Try to send ICMP “ping”, if that fails
  2.  Try to use ICMP Echo service
 
Unfortunately, check (1) can only be attempted if you run the app with an elevated permissions (root or sudo), which typically does not happen.
 
So it goes to (2) and makes the following attempt:
 
[rms@tr005buwls11 ~]$ sudo tcpdump -nn -v -i eth0 host tr005buece12 and port not 22
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
14:40:57.566469 IP (tos 0x0, ttl 64, id 64840, offset 0, flags [DF], proto TCP (6), length 60)
    131.116.167.11.55766 > 131.116.167.13.7: Flags [S], cksum 0xaf64 (correct), seq 562514241, win 14600, options [mss 1460,sackOK,TS val 300069897 ecr 0,nop,wscale 7], length 0
14:40:57.566522 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
    131.116.167.13.7 > 131.116.167.11.55766: Flags [R.], cksum 0x1628 (correct), seq 0, ack 562514242, win 0, length 0

So it probes Echo service over TCP port 7. 

Solution

Here you are! It was a missing firewall rule. Just open TCP/7 port on the target (checked) system and the test is passing like a charm.

Details for nerds

A small tool to run the test. Just run it as shown below:

[rms@tr005buece12 tmp]$ ./test.sh tr005buwls11.ddc.teliasonera.net
Testing tr005buwls11.ddc.teliasonera.net
OK

[rms@tr005buwls11 ~]$ sudo tcpdump -nn -v -i eth0 host tr005buece12 and port not 22
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
14:40:57.566469 IP (tos 0x0, ttl 64, id 64840, offset 0, flags [DF], proto TCP (6), length 60)
    131.116.167.11.55766 > 131.116.167.13.7: Flags [S], cksum 0xaf64 (correct), seq 562514241, win 14600, options [mss 1460,sackOK,TS val 300069897 ecr 0,nop,wscale 7], length 0
14:40:57.566522 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
    131.116.167.13.7 > 131.116.167.11.55766: Flags [R.], cksum 0x1628 (correct), seq 0, ack 562514242, win 0, length 0

Compare with same test ran using sudo. This time the test is done using ICMP, so no TCP/7 port needed. But as mentioned earlier, this is highly impractical and even not recommended:

[rms@tr005buece12 tmp]$ sudo ./test.sh tr005buwls11.ddc.teliasonera.net
Testing tr005buwls11.ddc.teliasonera.net
OK

tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
14:40:26.430473 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 72)
    131.116.167.11 > 131.116.167.13: ICMP echo request, id 12072, seq 1, length 52
14:40:26.430508 IP (tos 0x0, ttl 64, id 56716, offset 0, flags [none], proto ICMP (1), length 72)
    131.116.167.13 > 131.116.167.11: ICMP echo reply, id 12072, seq 1, length 52

Prometheus Node Exporter /lib/init/init-d-script: /usr/bin/daemon: not found

After Ubuntu upgrade 18.04 -> 18.10, Prometheus Node Exporter started to complain:

root@grafana:~# /etc/init.d/prometheus-node-exporter 
startStarting Prometheus exporter for machine metrics prometheus-node-exporter                                                         
/etc/init.d/prometheus-node-exporter: 45: /lib/init/init-d-script: /usr/bin/daemon: not found

Fix for this is quite easy – just install missing dependency:

root@grafana:~# apt install daemon
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  daemon
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 99.5 kB of archives.
After this operation, 288 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu cosmic/universe amd64 daemon amd64 0.6.4-1build1 [99.5 kB]
Fetched 99.5 kB in 0s (287 kB/s)
Selecting previously unselected package daemon.
(Reading database ... 22628 files and directories currently installed.)
Preparing to unpack .../daemon_0.6.4-1build1_amd64.deb ...
Unpacking daemon (0.6.4-1build1) ...
Processing triggers for man-db (2.8.4-2) ...
Setting up daemon (0.6.4-1build1) ...
root@grafana:~# /etc/init.d/prometheus-node-exporter stop
 * Stopping Prometheus exporter for machine metrics prometheus-node-exporter                                                  [ OK ]
root@grafana:~# /etc/init.d/prometheus-node-exporter start
 * Starting Prometheus exporter for machine metrics prometheus-node-exporter                                                  [ OK ]
root@grafana:~#

After that daemon can be started:

root@grafana:~# /etc/init.d/prometheus-node-exporter start
Starting Prometheus exporter for machine metrics prometheus-node-exporter                                                  [ OK ]
root@grafana:~#

Param2Clipboard

A MacOS application to grab an argument and set system Clipboard as per argument text.

How it works?

Under the hood it’s invoking pbcopy as below:

#!/bin/bash

if [[ -z "$1" ]]
then
  osascript -e 'display notification "Nothing copied!" with title "Param2Clipboard"'
else
	echo "$1" | pbcopy
	osascript -e 'display notification "Parameter copied to the Clipboard!" with title "Param2Clipboard"'
fi

The script has been wrapped into MacOS app using Platypus:

Flow

Eventually, registered required URL Types in Info.plist. Unfortunately, it was a manual process which has to be repeated every time when a new app is created using Platypus:

Flow

Why created?

Created to improve workflow when opening Microsoft Skype or Lync meetings.

Flow I’m using:

Flow

Broswer Fairy configuration

In order to capture opening of Skype/Lync URLs, I’m using Browser Fairy which is registered as a default app to open all URLs. Each URL is matched against defined list of patters and if a Skype URL is detected, the URL is passed to Param2Clipboard app.

Flow
Flow

References