Is it possible to simulate a temporary network disconnection from inside a Linux container?

152 Views Asked by At

Context

To perform some unit tests on a Linux (openSUSE Leap 15) application that runs on docker I have a manager that sends commands through sockets to app in docker.

Question

In this context, for some testing I want to be able to send a command to temporarily disable network from inside container, to be clear the command send/reception is not the issue but what I do when I receive such command, I tried ip link set eth0 down/up and down actually works but not up, here is an example to reproduce, with following docker file:

FROM opensuse/leap:15

# We just need ping and ip
RUN zypper --non-interactive --no-gpg-checks --ignore-unknown --no-cd in --auto-agree-with-licenses --allow-unsigned-rpm ping iproute2

ENTRYPOINT [ "bash" ]
  • Build image with docker build -t opensuse-leap-15-if-down-up:1.0 .,
  • Run with docker run -dti --cap-add NET_ADMIN --hostname opensuse-leap-15-if-down-up --name opensuse-leap-15-if-down-up opensuse-leap-15-if-down-up:1.0,
  • Exec with docker exec -ti opensuse-leap-15-if-down-up bash,
  • From inside container:
    • ping google.com to check you can reach it,
    • ip link set eth0 down to deactivate eth0 interface,
    • ping google.com again to check you cannot anymore: OK, "ping: google.com: Temporary failure in name resolution" error,
    • ip link set eth0 up to reactivate eth0 interface,
    • ping google.com again to check it is fine: KO, still got "ping: google.com: Temporary failure in name resolution" error.

Any idea why this does not work or idea on how to simulate a temporary network disconnection from inside a Linux container ?

Edit: I also tried systemctl stop systemd-networkd without success (ping google.com still answers after stop) and I saw there is a systemd-networkd-wait-online.service too, not sure what it does but stopping it does not disconnect network too.

Edit2: I also tried this but route add default gw 172.17.0.1 gives me SIOCADDRT: Network is unreachable, and not I had to install net-tools-deprecated package to get route command what I don't want if possible. But I'm not so familiar with ip route commands and for instance ip r add 172.17.0.1/8 dev eth0 and other tests always gave me Error: Invalid prefix for given prefix length error.

Final edit: I thought because of my context I was not duplicate of How to disable and enable internet connection from within Docker container?, but finally I am since my answer is inspired from an answer here, I then added a vote to close mine as duplicate.

1

There are 1 best solutions below

3
gluttony On

Based on this answer in another question that gave me a clue, but route add default gw 172.17.0.1 does not work for me (gives me SIOCADDRT: Network is unreachable error), finally in addition with @KamilCuk comment in my question I got network again with:

ip link set eth0 up
ip route add default via 172.17.0.1 dev eth0

Then I can disconnect with:

ip link set eth0 down

And reconnect with up then route add above to simulate a temporary network disconnect.

Edit: after actually using it in docker compose I've seen IP may vary, at least between a launch with docker run or docker-compose up, I then did a DisconnectReconnectNetwork.sh script that does this:

#!/bin/bash

DEFAULT_VIA=$(ip r | grep "default via")
ip link set eth0 down
ip link set eth0 up
# Disable https://www.shellcheck.net/wiki/SC2086 (double quote to prevent globbing and word splitting)
# for DEFAULT_VIA since else it is not taken properly by ip route add
# shellcheck disable=SC2086
ip route add ${DEFAULT_VIA}