On 2010 RIPE Network Coordination Centre (RIPE NCC) established a distributed platform for Internet measurements called “RIPE Atlas”.
The project consists of multiple hardware devices, called probes, that conduct measurements such as ping and traceroute to specific destinations.
The concept is to hand over RIPE Atlas probes free of change to volunteers, which in turn install them to their networks and contribute a small portion of their bandwidth to the project.
As an incentive, RIPE provides “credits” to volunteers based on their probe uptime. So the more the uptime your probe has, the more the credits you get.
Credits can be redeemed, by creating and conducting custom measurements on the platform.
Currently, more than 11.000 probes have been deployed globally and many network tools have been developed, based on this platform.
One of those probes is hosted on my parent’s house in Heraklion, Crete since 2013.

In February 2020, RIPE announced the availability of software probes, to improve platform coverage even on smaller networks. So instead of installing a network device (the probe) to your network, you install the software package for the probe in a machine connected to your network.
RIPE provides packages to install the probe at CentOS and Debian distributions. There is even a Docker image developed by the community.
I used the latter option, to host another probe on my home’s OrangePI.

One might reasonably wonder though. “Hey, do you trust that this device won’t intercept your local network traffic, or tamper with your other devices in any way?”.
As stated on the FAQ, the probe executes measurement commands against the public internet only.
For the security cautious, it is advised that the probe should be install outside of one’s local network (e.g on a DMZ network). I had followed this recommendation on my hardware probe before, but how am I going to perform such isolation in Docker?
To make matters worse, I am using the CPE provided by my ISP, which has very limited capabilities in terms of configuring new networks.
One possible solution is to reject any traffic from probe’s network to internal networks via iptables.
However, this would require additional steps when redeploying the atlas probe. Ideally, my goal is to deploy the software probe out-of-the-box using a Docker compose manifest, without any additional commands.

So what if network traffic of our software probe container can be proxied to another service, which in turn tunnels it to the public Internet?
In this post we are going to describe how to achieve this, by spinning up a dedicated PPP connection with our ISP in Docker and use it as a “gateway” to our software probe container.


The overall design can be depicted on the following figure

Overall design

Our goal is to initiate a new PPPoE connection from a container inside an isolated network. Thus our ripe-atlas probe can only perform its measurements only via ppp connection, and without interfering with adjacent containers on the same host.

PPP client

There are two prerequisites so that ppp is established correctly. First of all you need to ensure that the CPE (modem/router) of your ISP has “PPPoE Passthrough” enabled. Some ISPs have this setting enabled by default.
Next, is to retrieve your ISP username and password. Some ISPs (like mine) had handed over the username and password on paper along with my CPE equipment. On other circumstances, you might want to fetch a configuration backup from your CPE and retrieve credentials from it. YMMV. With those in hand we can proceed with configuring ppp client.

Required ppp configuration can be easily generated using pppoeconf tool. It is an ncurses based tool that helps you populate /etc/ppp/peers/dsl-provider and /etc/ppp/chap-secrets with the correct values.
Next step, is to dockerise the ppp client. I created a small Docker image (tzermias/ppp) that it simply invokes ppp client.
Providing that our configuration is under a file named “dsl-provider” and located under /etc/ppp/peers directory, we could invoke the container as follows:

$ docker run --name ppp -d --privileged \
     --device=/dev/ppp \
     - v/etc/ppp:/etc/ppp \
     tzermias/ppp call dsl-provider

ppp client requires access to /dev/ppp device to work properly, so we need to expose it accordingly.
Furthermore, you need to use macvlan network driver for the ppp container to work properly.
A dedicated macvlan network can be created using the command below.

$ docker network create -d macvlan \
     --subnet= \
     -o parent=eth0 ppp

The ppp container can be attached to the network by adding the --network ppp flag on the docker run command above.

If everything went well, logs of ppp container would indicate a successful call is performed and a new IPv4 address is assigned to ppp0 interface of our container.

$ docker logs ppp
Plugin rp-pppoe.so loaded.
PPP session is 394
Connected to d8:67:d9:48:XX:XX via interface eth0
Using interface ppp0
Connect: ppp0 <--> eth0
PAP authentication succeeded
peer from calling number D8:67:D9:48:XX:XX authorized
local  LL address fe80::dead:beef:dead:beed
remote LL address fe80::beef:beef:dead:dead
replacing old default route to eth0 []
local  IP address XX.XX.XX.XX
remote IP address YY.YY.YY.YY

ppp client will also create a resolv.conf file under /etc/ppp, containing DNS nameservers obtained from our peer.
For this, you need to have the usepeerdns option in your /etc/ppp/peers/dsl-provider file.

Container networking

Now comes the interesting part. How can we ensure that any network traffic from our ripe-atlas container will only pass through the ppp container we started earlier?
The answer is to share the network stack of this container. Apart from the usual bridge, host or none options that one can pass to --network setting, there a special option named container which allows you to use the network stack of another container.
According to docker run reference:

With the network set to container a container will share the network stack of another container. The other container’s name must be provided in the format of –network container:<name|id>.

Example running a Redis container with Redis binding to localhost then running the redis-cli command and connecting to the Redis server over the localhost interface.

With ppp container running, we can easily validate that our setup works, just by spinning up a test container as follows, and perform some tests (e.g a traceroute).
Don’t forget to mount /etc/ppp/resolv.conf file in this container in order to have proper DNS resolution.

$ docker run -it --network ppp -v /etc/ppp/resolv.conf:/etc/resolv.conf:ro busybox:latest traceroute google.com

Now we are ready to spin up our ripe-atlas probe!

RIPE Atlas in Docker

I used ripe-atlas image by jamesits for this purpose. Probe installation and registration are straightforward and well-documented.
On first run, probe generates an SSH keypair and saves it under /var/atlas-probe/etc/probe-key.pub.
Simply create a new directory where any relevant ripe-atlas files will be stored and mount it to the container.

$ mkdir -p atlas-probe

$ docker run --network "container:ppp" \
        --detach --restart=always --log-opt max-size=10m \
	--cpus=1 --memory=64m --memory-reservation=64m \
	--cap-add=SYS_ADMIN --cap-add=NET_RAW --cap-add=CHOWN \
	--mount type=tmpfs,destination=/var/atlasdata,tmpfs-size=64M \
	-v ${PWD}/atlas-probe/etc:/var/atlas-probe/etc \
	-v ${PWD}/atlas-probe/status:/var/atlas-probe/status \
        -v /etc/ppp/resolv.conf:/etc/resolv.conf:ro \
	-e RXTXRPT=yes --name ripe-atlas \

After uploading the probe’s public key to RIPE Atlas WebUI, probe is ready to accept new measurements.

IPv6 support

For those who wish the probe run IPv6 measurements, you can enable IPv6 support by performing the following modifications:

Firstly you need to enable IPv6 support in Docker daemon. Ensure that your /etc/docker/daemon.json contains the following:

  "ipv6": true,
  "fixed-cidr-v6": "2001:db8:1::/64"

Then, ensure that Docker daemon is aware of those settings

$ systemctl restart docker

Next step is to make sure that our ppp container has IPv6 support enabled. For this we need to start our container with net.ipv6.conf.all.disable_ipv6=0 set.

And the last step (eventually) is to enable IPv6 support when performing the PPP call. This can be achieved by adding the following two options in our /etc/ppp/peers/dsl-provider config.


Putting it together

To sum up, one should execute the following commands to have the probe and the ppp client up and running:

I also created the following docker-compose.yaml file to spin up the network and the containers to avoid typing those commands again and again.

For those who wish to use this probe for their measurements, just use probe #1001487.

Software probes can increase the reach of RIPE Atlas platforms on more networks and geographic locations.
From 260 probes currently deployed in Greece, we can clearly observe a large portion of them being deployed in Athens metro area.
Wouldn’t be nice to have Internet measurements on less densely populated areas, like islands?
Furthermore, the option to share one container’s network stack with another can be leveraged on other applications, like proxying traffic through a VPN tunnel.
If you have a RaspberryPi sitting idle on your network, I’d suggest you give this option a try!