Measuring IP Connectivity with RIPE Atlas

One of the most important but often overlooked criteria when choosing a hosting provider is the performance of its network. Poor network performance for any kind of online service leads to low customer satisfaction. What is the best way to measure network performance that most accurately simulates a customers experience with a network? We found this question to be an interesting idea to explore during a Leaseweb hackathon!

RIPE Atlas

RIPE Atlas is the RIPE NCC’s main Internet data collection system. Its a global network of devices, called probes and anchors, that actively measure Internet connectivity. Anyone can access this data via Internet traffic maps, streaming data visualizations, and an API. RIPE Atlas users can also perform customized measurements to gain valuable data about their own networks.

Due to the size and reach of the Atlas project, it’s one of the most important internet measurement initiatives internationally. What’s great is that the project is run by RIPE, but driven by the global community of RIPE members (and non-members!) who contribute some of their resources to help the project. This improves visibility into the inner-workings of the global Internet. It’s used by Internet professionals all over the world to improve quality of their network, debug issues, and learn. Leaseweb contributes to the RIPE Atlas by hosting 7 ‘anchors’ in various data centers all over the globe.

Since Leaseweb already contributes to RIPE Atlas with these anchors, it’s an obvious choice as a source of random probes to be used against those anchors and compared with other infrastructure providers’ anchors. (By the way, if you would like to do your own measurements and contribute to the RIPE Atlas project at the same time, you can request a probe for your home or office right here!). You can read more on the structure of the Atlas network (and how probes, anchors and the RIPE backend work together) in various posts on the RIPE labs pages.

The main elements needed to use RIPE Atlas are measurements, sources and targets. These elements all have their own function to facilitate experiments.

Getting The Data

Triggering one-off measurements and fetching the results of those measurements can be done using the RIPE Atlas API. RIPE-NCC also developed a wrapper around the RIPE Atlas API to allow anyone to communicate with the RIPE Atlas API using Python. It is maintained by RIPE Atlas developers and is therefore the best choice for consuming their API. Using it requires an API key. Wrapper is open-source and available on GitHub.

Installation is very simple using pip:

$ pip install ripe.atlas.cousteau

Included classes in the Python script:

from ripe.atlas.cousteau import (
Ping,
Traceroute,
AtlasSource,
AtlasCreateRequest,
AtlasLatestRequest
)

Measurement Types

RIPE Atlas offers several measurement types – Ping, Traceroute, DNS, HTTP, SSL, NTP, and WiFi. Creating a measurement allows you to specify a type of test (or ‘experiment’) to perform. Typically, these have something to do with latency for a service, but there are also options to check things like resolving a domain name and checking DNS propagation. These measurements can be one-off or recurring. For our Hackathon project we used one-off measurements.

Sources

Probes defined as sources are used to trigger the measurement. They can be defined explicitly or taken from a pool (area, country, prefix or AS number). Below, the defined source takes 50 random probes from Europe to be used as a source of measurement.

source = AtlasSource(
    type="area",
    value= "North-Central",
    requested=50
)

Targets

Targeted IPs that the measurements are run against. In this example, ping is run against one of Leaseweb’s anchors.

pingLSW = Ping(
    af=4,
    target="5.79.112.97", 
    description="Ping nl-haa-as60781.anchors.atlas.ripe.net"
)

Create Request

Defining a request combines all of the elements together: measurements and sources. It also requires a start time, API key and – in this case – a one-off flag.

atlas_request = AtlasCreateRequest(
    start_time=datetime.utcnow(),
    key=ATLAS_API_KEY,
    measurements=[pingLSW, pingOVH, pingAzure, pingAWS, pingUni],
    sources=,
    is_oneoff=True
    )

To summarize what this request will do:

  • We specify a number of ping tests to various endpoints
  • We specify where we want to have those request come from and how many we want
  • …and we bundle those tests into a single one-off request.

Calling RIPE Atlas API now is simple

response = atlas_request.create()

After calling this function, Atlas will launch tests towards 50 random probes in the area we designated, and will store the results.

Returned values, stored in response, are measurement counts. In this case, there are 5 values as there are 5 measurements defined. The actual results have to be retrieved separately, so the next step is fetching the measurement data. Here, class AtlasLatestRequest is used:

results = AtlasLatestRequest(msm_id=measurement_id).create()

The results variable now has stored all of the measurement details needed to calculate and compare latencies. It’s clear to see how powerful Atlas is. In a few simple lines we’ve generated latency information from 50 end points to multiple targets!

Visualizing Data

Visualizing data that was fetched from RIPE Atlas API was done with pygal Python library that supports various chart types and styles. For this Hackathon project pygal.Bar() was used to draw out the comparison results. (Pygal usage is out of the scope of this blog post). Two charts below show the data from measurements taken from Europe and from Russia.

Conclusion and Going Forward

This Hackathon project showed the basic features of RIPE Atlas and what it can accomplish.  RIPE Atlas also maintains a parsing library name Sagan, available in GitHub, that handles format changes in measurement results and always returns a native Python object.

RIPE Atlas has a huge amount of functionality and can be easily used in your own experiments and measurements. Remember to always use the Atlas infrastructure responsibly.

Other tools for using permanent measurementsstreaming data, and building dashboards are RIPE Prometheus exporter, working as a metric exporter of RIPE Atlas measurement results that exports collected metrics to Prometheus. Grafana is common tool that works well with Prometheus to create dashboards with useful metrics, gathered from RIPE Atlas measurements.  

Comments? Questions? Other ways to use RIPE Atlas and receive measurements? I’d love to hear your feedback! 

Share

Detecting torrent traffic on a Linux box

torrent_detection

At home I am sharing my Internet connection with several other family members. Sometimes my Internet is very slow with high latencies, causing my interactive SSH connections to stutter. The problem is always the same: somebody is downloading a torrent. And although I have no objection against torrent technology (it has many good applications), I hate it when I cannot work properly on my remote servers. So I decided to take action.

Wireshark and Tshark to the rescue

Wireshark has a command line version called “tshark”. It has a bittorent protocol analyzer and can be used to do Deep Packet Inspection (DPI). I decided to make a simple script that runs every 5 minutes and samples the network traffic for 10 seconds. After that it sends a report (top list, including packet count) of the local IP addresses that do the most torrent traffic (if there are any).  It can be ran using:

sudo tshark -a "duration:10" -Y bittorrent -f 'not port 80 and not port 22 and not port 443' | grep -o "192\.168\.1\.[0-9]\+" | sort | uniq -c | sort -rn | head | mail -E -s "LAN abusers" maurits@vdschee.nl

It is using postfix to send email via the gmail SMTP server (gmail account required). I am runnig the above in a cron job every 5 minutes. You may simply run this script on the gateway of your network. In case you can setup a port mirror on the switch of your up-link, then you can run this in promiscuous mode. Tshark will try to enable this mode by default, if it does not work, then check the FAQ here.

Blocking on detection

There are several ways to block the user that is abusing your network. I feel that temporary null routing the IP address is the simplest way. Additionally you may add an entry to your DHCP lease table to avoid that the user can simply request a new IP address. Filtering the good from the bad traffic is actually much more complicated. For one, because you need to find all the bad packets (as the software may try to avoid the block, switching protocols). If you really want to give it a try, you may look at netfilter string match. If you do, then make sure you enter good offsets and ranges to avoid negative performance impact on your network. Also I would not know where to get a maintained and complete set of protocol signatures.

torrent_utp_detection

Detecting uTP

If you are using the “Deluge” torrent client, you will be quickly detected by the above script. When you are using “Transmission” (another client) you may get away undetected. This is caused by the Micro Transport Protocol (aka “uTP”). This is a UDP based torrent protocol that cannot be recognized by Tshark yet. It is not very hard to actually make a custom rule that detects “uTP”. This is the custom filter:

sudo tshark -a "duration:10" -Y 'udp[8:5] == "\x64\x32\x3A\x69\x70" or bittorrent' -f 'not port 80 and not port 22 and not port 443' | grep -o "192\.168\.1\.[0-9]\+" | sort | uniq -c | sort -rn | head | mail -E -s "LAN abusers" maurits@vdschee.nl

The above command will detect also the “undetectable” uTP protocol. You may even extend the match a little as there are more fixed position bytes that can be matched.

Share

Fast dynamic DNS with cron, PHP and DuckDNS

ducky_icon_mediumMy home connection has a 200 mbit cable Internet connection with 20 mbit up. Great for running a server, but every two days my ISP changes my IP address. When this happens I cannot connect to my home network anymore using VPN. Annoying, but certainly a (programming) challenge to me. The simple solution for this is to use a dynamic DNS solution. The name DynDNS popped up in my head, but apparently they are not free anymore (bummer). That’s why I chose to use the free dynamic DNS service “DuckDNS“. Then I realized that I do want a fast update of my dynamic DNS entry when my IP address changes, but I do not want to hammer DuckDNS. That’s why I wrote a small script to achieve this. You find it below.

DuckDNS PHP script to avoid hammering

On my website I installed the following PHP script that will call DuckDNS if the IP address of the caller has changed. It is must be called with a post request that holds a shared secret. This will avoid bots (or hackers) to change the DNS entry. Note that additionally HTTPS (SSL) is used to guarantee confidentiality.

<?php
// settings
$domains = 'cable-at-home'; // cable-at-home.duckdns.org
$token = 'eb1183a2-153b-11e5-b60b-1697f925ec7b';
$ip = $_SERVER['REMOTE_ADDR'];
$file = '/tmp/duckdns.txt';
$secret = 'VeryHardToGuess';
// compare secret
if (!isset($_POST['secret']) || $_POST['secret']!=$secret) { http_response_code(403); die(); }
// compare with current ip
if ($ip==file_get_contents($file)) { http_response_code(304); die('OK'); }
// create url
$url = "https://www.duckdns.org/update?domains=$domains&token=$token&ip=$ip";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($ch);
curl_close($ch);
// if success update current ip
if ($result!='OK') { http_response_code(400); die($result); }
file_put_contents($file,$ip);
die('OK');

Install this script somewhere in your Apache “DocumentRoot” and name it “duckdns.php”.

Cron script that runs every minute

I installed the following cron job on my server that runs in my home and is connected with cable to the Internet using the “crontab -e” command:

* * * * * /usr/bin/curl -X POST -d 'secret=VeryHardToGuess' https://somedomain.com/duckdns.php

Every minute this cron job executes a curl call to the duckdns.php PHP script on my website (somedomain.com). Only if the IP address is changed the call to DuckDNS (https://www.duckdns.org/update) is made to update the IP address. This avoids hammering the DuckDNS service, but also allows you to get the fastest response to an IP address change.

Installation

Note that in order to make this work you have to create an account at DuckDNS and then modify the “$domains” and “$token” parameters in the PHP script accordingly. You need to change “somedomain.com” in the cron job with the URL of your website. Also do not forget to replace “VeryHardToGuess” in both the PHP script as the cron job with a real secret. Any questions? Use the comments below!

Share

Linux multi-player command line games (daemon-games)

snaked

Daemon-games is a set of multi-user console games for Linux. The name is a tribute to the well known Debian “bsdgames” package. A “daemon” is defined in Wikipedia as:

In multitasking computer operating systems, a daemon (/ˈdiːmən/ or /ˈdeɪmən/) is a computer program that runs as a background process, rather than being under the direct control of an interactive user. – Wikipedia

The first game in this series is multi-player snake and it is named “snaked” (the “d” is for daemon). You can see it in the screen-shot above. The next game I want to make is multi-player tetris (named “tetrisd”).

Implemented in C

This server is implemented in C. You can find the common code in the files “daemon.c” and “daemon.h”. It aims to be a simple implementation and that is why it is using the “select” call. The select call waits for input on a set of sockets (or file descriptors). When one of them has data the call returns and you can handle the socket(s) that have data. The server calculates the screens and sends them over in ANSI. It also calculates the differences between frames to reduce bandwidth. All user input is directly forwarded to the server.

Getting started with “snaked”

Running the server is as easy as:

git clone https://github.com/mevdschee/daemon-games
cd daemon-games
make
./snaked 9000

Running the client is as easy as:

wget https://raw.githubusercontent.com/mevdschee/daemon-games/master/client.sh
bash client.sh 127.0.0.1 9000

You should replace “127.0.0.1” by the IP address of the server. The number “9000” is the TCP port the server runs on. You can easily review the client to see that it actually just running netcat. You can play with the “wasd” keys and “q” for quit.

Download the source code

You can! Please play with it and send me improvements or make complete new games. I would love to accept any PR. All code is on GitHub:

https://github.com/mevdschee/daemon-games
Share

Use Ubuntu’s “hostapd” to monitor your smartphone

I don’t like smart-phones at all. I do not like how people use them in bars and restaurants. I also don’t like that the phone is always online. Especially not since all kinds of “apps” and background processes are constant leaking information about me. Call me a fool, but I’m worried about my privacy. Since my friends nowadays refuse to send me SMS (they solely rely on WhatsApp) I was getting socially isolated (showing up at canceled events and so on). That is why I recently gave up my stubbornness and decided to buy a smartphone as well. Still everyday I am wondering what (and how) my smartphone is communicating over the Internet. To get an answer to this question I decided to investigate this.

Parts

SitecomWL113WirelessNetworkUSBAdapter wireshark

I had the above Sitecom (WL-113) USB wifi dongle laying around that could serve as an access point for my phone so that I could peek into the communication on my PC using the excellent open source Wireshark software. This is a diagram of the infrastructure:

wl-113_network

I am running Xubuntu 14.04 and I connected my USB dongle.

Preparation

First I ran “lsusb” to confirm the adapter was identified.

maurits@nuc:~$ lsusb
...
Bus 002 Device 024: ID 0df6:9071 Sitecom Europe B.V. WL-113 rev 1 Wireless Network USB Adapter

And yes it was. Great! Now to see what the system says about it when I connected it. Running “dmesg” showed me the driver that was loaded:

maurits@nuc:~$ dmesg
...
[20068.576242] usb 2-1.4: new high-speed USB device number 24 using ehci-pci
[20068.669492] usb 2-1.4: New USB device found, idVendor=0df6, idProduct=9071
[20068.669498] usb 2-1.4: New USB device strings: Mfr=16, Product=32, SerialNumber=0
[20068.669501] usb 2-1.4: Product: USB2.0 WLAN
[20068.669504] usb 2-1.4: Manufacturer: Sitecom
[20068.744236] usb 2-1.4: reset high-speed USB device number 24 using ehci-pci
[20068.837283] ieee80211 phy12: Selected rate control algorithm 'minstrel_ht'
[20068.837521] zd1211rw 2-1.4:1.0: phy12
[20068.855382] IPv6: ADDRCONF(NETDEV_UP): wlan0: link is not ready

To see whether the adapter was really there I ran “ifconfig -a” and yes it was and it was named “wlan0”:

maurits@nuc:~$ ifconfig -a
...
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:5387 errors:0 dropped:0 overruns:0 frame:0
          TX packets:5387 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:634228 (634.2 KB)  TX bytes:634228 (634.2 KB)

wlan0     Link encap:Ethernet  HWaddr 00:00:de:ad:be:ef
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

I did get a little curious of what the dongle would look like on the inside, so I Googled for “zydas wl-113”. I found the following image on Wireless-Forum.ch:

wl-113

I also found a guy who had a Sitecom WL-113 with a Ralink 2571WF chip inside (probably not a “rev 1” model). But I am pretty sure mine has a ZyDAS 1211 as in the above picture (but I did not open it up). Before we can do “nice” things with it we need to see whether it supports “master mode“. This means that the dongle goes into a mode in which it behaves as an access point. Ubuntu has a tool called “iw” (install it with “sudo apt-get install iw”) that allows you to list the supported modes (amongst many other things) like this:

maurits@nuc:~$ iw list
Wiphy phy12
    ...
    Supported interface modes:
         * IBSS
         * managed
         * AP
         * AP/VLAN
         * monitor
         * mesh point

Bingo! Our dongle supports “AP” mode (many devices do not). You may want to try to put the adapter in master mode with the following command:

maurits@nuc:~$ iwconfig wlan0 mode master
Error for wireless request "Set Mode" (8B06) :
    SET failed on device wlan0 ; Operation not permitted.

But that fails. After reading the web a little I found that this does not mean that the dongle does not support it.

Installing “hostapd” the host access point daemon

You just need to install “hostapd” program using “sudo apt-get install hostapd”. Before you can start the hostapd application you need to take a few steps. First I had to create the “/etc/hostapd/hostapd.conf” file with the following contents:

interface=wlan0
bridge=br0
driver=nl80211
ssid=MyNetwork
hw_mode=g
channel=7
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=3
wpa_passphrase=YourPassPhrase
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

Now edit the file “/etc/default/hostapd” and uncomment the “DAEMON_CONF” line and make it:

DAEMON_CONF="/etc/hostapd/hostapd.conf"

If we want the PC to temporarily act like a router we need to enable IPv4 forwarding:

sudo sysctl -w net.ipv4.ip_forward=1

Now you can start the “hostapd” access point software with:

sudo hostapd /etc/hostapd/hostapd.conf

If all goes well it should show:

maurits@nuc:~$ sudo hostapd /etc/hostapd/hostapd.conf
Configuration file: /etc/hostapd/hostapd.conf
Using interface wlan0 with hwaddr 00:00:de:ad:be:ef and ssid "MyNetwork"
wlan0: interface state UNINITIALIZED->ENABLED
wlan0: AP-ENABLED

If it does not work you may want to run the following:

sudo nmcli nm wifi off
sudo rfkill unblock wlan

This is because network manager has detected the wlan interface and grabbed it. If you need debug output you may run:

sudo hostapd -d /etc/hostapd/hostapd.conf

If you need even more debug output you may run:

sudo hostapd -dd /etc/hostapd/hostapd.conf

If this fails with the following message:

hostapd_free_hapd_data: Interface wlan0 wasn't started

Then execute:

sudo service hostapd stop

If it says it started (using “sudo hostapd”), but you actually don’t see the Wifi network on your smartphone then reconnecting the dongle and starting all over again may help. Note that the “hostapd” service will automatically be started on next boot.

Bridging to get Internet access

bridge_configuration

Now you may want to configure a bridge between eth0 (your Internet connection) and wlan0 (your dongle access point). First we remove the IP address from eth0 using. Then we add eth0 to bridge br0 (which already contains wlan0). After that we bring the bridge up, let it do DHCP and which also adds a default route to the gateway using:

sudo ifconfig eth0 inet 0.0.0.0
sudo brctl addif br0 eth0
sudo ifconfig br0 up
sudo dhclient br0

Now you should still be able to surf the Internet while you also have a software access point running on your computer. If you want to undo the bridge configuration you may run:

sudo ifconfig br0 down
sudo brctl delif br0 wlan0
sudo brctl delif br0 eth0
sudo ifconfig br0 down
sudo dhclient eth0

Permanent configuration (persist on reboot)

The IPv4 forwarding setting can be made permanent by uncommenting the following line in “/etc/sysctl.conf”:

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

If you want to make the bridge configuration permanent you can add the following to “/etc/network/interfaces”:

manual wlan0
manual eth0

auto br0
iface br0 inet dhcp
        bridge_ports eth0

Note that this wont work since the network manager will still grab the wlan0 and execute “rfkill”. To avoid this you can turn off the network manager completely (and permanently) with:

sudo service network-manager stop
echo "manual" | sudo tee /etc/init/network-manager.override

To re-enable the network manager simply do the opposite:

sudo rm /etc/init/network-manager.override
sudo service network-manager start

Capturing with Wifi with Wireshark

Now we can start Wireshark on the wlan0 interface using:

sudo wireshark wlan0

And we get nice output:

wireshark_dump

Using this tool I can record and analyze the communication of the apps I installed on my smartphone.

Links/sources

Figuring all the above out was not possible without the following websites:

Share