Author: Jarek

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

Withings to Garmin Connect – resurrection

After dropping “legacy” APIs on Withings page, the script stopped to work…

It took quite a while to adjust it to OAuth2 but finally – it’s done!

Go to https://github.com/jaroslawhartman/withings-garmin-v2 to download the script.

References

  • Based on withings-garmin by Masayuki Hamasaki, improved to support SSO authorization in Garmin Connect 2.
  • SSO authorization derived from https://github.com/cpfair/tapiriik

Pre-requisites

$ sudo easy_install requests
  • simplejson
$ sudo easy_install simplejson

Usage

Usage: $python 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.
  -f <date>, --fromdate=<date>
  -t <date>, --todate=<date>
  --no-upload           Won't upload to Garmin Connect and output binary-
                        string to stdout.
  -v, --verbose         Run verbosely

Obtaining Withings Authorization Code

When running for a very first time, you need to obtain Withings authorization:

$ ./sync.py -f 2019-01-25 -v
Can't read config file config/withings_user.json
***************************************
*         W A R N I N G               *
***************************************

User interaction needed to get Authentification Code from Withings!

Open the following URL in your web browser and copy back the token. You will have *30 seconds* before the token expires. HURRY UP!
(This is one-time activity)

https://account.withings.com/oauth2_user/authorize2?response_type=code&client_id=183e03e1f363110b3551f96765c98c10e8f1aa647a37067a1cb64bbbaf491626&state=OK&scope=user.metrics&redirect_uri=https://wieloryb.uk.to/withings/withings.html&

Token : _

You need to visit the URL listed by the script and then – copy Authentification Code back to the prompt.

This is one-time activity and it will not be needed to repeat.

Tips

You can hardcode your usernames and passwords in the script (sync.py):

GARMIN_USERNAME = ''
GARMIN_PASSWORD = ''

For advanced users – registering own Withings application

The script has been registered as a Withings application and got assigned Client ID and Consumer Secret. If you wish to create your own application – feel free!

Note, registering it is quite cumbersome, as you need to have a callback URL and an Icon. Anyway, when done, you should have the following identifiers:

IdentfierExample
Client ID183e03.................765c98c10e8f1aa647a37067a1......baf491626
Consumer Secreta75d65.................4c16719ef7bd69fa7c5d3fd0ea......ed48f1765
Callback URIhttps://jhartman.pl/withings/notify

Configure them in config/withings_app.json, for example:

{
    "callback_url": "https://wieloryb.uk.to/withings/withings.html",
    "client_id": "183e0******0b3551f96765c98c1******b64bbbaf491626",
    "consumer_secret": "a75d65******1df1514c16719ef7bd69fa7*****2e2b0ed48f1765"
}