Diagnose Network Problems In A Container Using The Filesystem

So you need to figure out why you application is not working, but your toolset is very limited because you are using either a minimal installation of Linux or you are in a container. This technique should work either way.

You can use the /dev filesystem to check network connections.

Example 1:
You would like to know if you can reach the host 172.16.0.10 on port 443.

ip=172.16.0.10
port=443
if $((echo > /dev/tcp/$ip/$port) &>/dev/null)
then echo "TCP port $port is open"
else echo "TCP port $port is closed"
fi

The above command will you the answer.

You can also write this as a one-liner

ip=172.16.0.10;port=443; (echo > /dev/tcp/$ip/$port) &>/dev/null && echo "TCP port $port is open" || echo "TCP port $port is closed"

Example 2:

You would like to know what connections are being made to and from the container or host, but you do not have netstat.

Using the /proc filesystem you can list the connections. They are available in /proc/net/tcp, /proc/net/tcp6, /proc/net/udp and /proc/net/udp6. So you can just dump the output on these files and they will show you. Unfortunately they are in HEX, but do not worry. Here is a function that will convert them for you.

One catch. The script will only handle ipv4, so for ipv6 you are on your own as it does not make sense to convert them since ipv6 is always HEX. You could convert the port number if you wanted to though.

Anyway here is the function:

function list_network_connections {
    if [ -z "$1" ]; then
        echo "Usage: list_tcp_connections <filename>"
        return 1
    fi

    # Print TCP connections with IPs and ports converted from hex to decimal
    cat "$1" | grep -v sl | awk '{
        # Convert IP and port from hex to decimal using system shell
        split($2, a, ":");
        split($3, b, ":");

        # Extract IP components in hexadecimal
        src_ip_hex = substr(a[1], 7, 2) substr(a[1], 5, 2) substr(a[1], 3, 2) substr(a[1], 1, 2);
        dst_ip_hex = substr(b[1], 7, 2) substr(b[1], 5, 2) substr(b[1], 3, 2) substr(b[1], 1, 2);

        # Convert hex to decimal for IPs
        cmd = "echo $((0x" src_ip_hex "))";
        cmd | getline src_ip_dec; close(cmd);
        cmd = "echo $((0x" dst_ip_hex "))";
        cmd | getline dst_ip_dec; close(cmd);

        # Convert ports from hex to decimal
        src_port = sprintf("%d", "0x" a[2]);
        dst_port = sprintf("%d", "0x" b[2]);

        # IP decimal to dot notation
        src_ip = int(src_ip_dec / (256^3)) "." int(src_ip_dec % (256^3) / (256^2)) "." int(src_ip_dec % (256^2) / 256) "." int(src_ip_dec % 256);
        dst_ip = int(dst_ip_dec / (256^3)) "." int(dst_ip_dec % (256^3) / (256^2)) "." int(dst_ip_dec % (256^2) / 256) "." int(dst_ip_dec % 256);

        print src_ip ":" src_port " " dst_ip ":" dst_port
    }'
}

function list_all_network_connections {
    cat /proc/net/udp | head -n 1 | awk '{print $2 " " $3}'
    list_network_connections /proc/net/tcp
    list_network_connections /proc/net/udp
}

Now you can dump them anytime using:

list_all_network_connections

Hope it helps you out. Let me know if you can similar tricks.

Leave a Reply

Your email address will not be published. Required fields are marked *