Skip to content

Instantly share code, notes, and snippets.

@mathershifter
Last active October 30, 2020 17:38
Show Gist options
  • Save mathershifter/73c38cedcc4f3437d986a52f0cacca37 to your computer and use it in GitHub Desktop.
Save mathershifter/73c38cedcc4f3437d986a52f0cacca37 to your computer and use it in GitHub Desktop.
Example docker network to source packets from a specific IP address/interface

Example TOPO:

[      Node A     ]           [        Node B       ]           [     Node C      ]
[Lo0:1.1.1.1] [et0] <- Eth -> [et0] lo0:1.1.1.2 [et1] <- Eth -> [et1] [lo0:1.1.1.3]

Note: EtX interface IP addresses are not advertised; packets must be sourced from a loopback interface to make a successful round trip.

Sample Script

#!/bin/sh

usage()
{
  echo "Usage: $0 -i INTERFACE -n NAME "
  exit 2
}

while getopts "i:n:h" flag; do
    case "${flag}" in
        i)
            interface=${OPTARG}
            ;;
        n)
            name=${OPTARG}
            ;;
        h)
            usage
            ;;
        *)
            echo "Invalid options provided"
            usage
            ;;
    esac
done

if [ -z "${interface}" ] || [ -z "${name}" ]; then
    usage
fi

bridge=br-${name}
source_address=`ip addr show ${interface} | grep -Po 'inet \K[\d.]+'`

# make sure the source interface has an IP address
if [ -z ${source_address} ]; then
    echo "ERROR: Unable to find the IP address for interface ${interface}"
    exit 1
fi

# cache sudo creds before continuing
if ! sudo -v; then
    echo "EROR: authorization failed, exiting."
    exit 1
fi

docker network create --attachable \
    --opt "com.docker.network.bridge.name=${bridge}" \
    --opt "com.docker.network.bridge.enable_ip_masquerade=false" \
    ${name}

if [ $? -ne 0 ]; then
    echo "ERROR: Failed to create docker network"
    exit 1
fi

subnet=`docker network inspect ${name} -f '{{ (index .IPAM.Config 0).Subnet }}'`

if [ $? -ne 0 ]; then
    echo "ERROR: Failed to inspect docker network: ${name}"
    exit 1
fi

if [ -z ${subnet} ]; then
    echo "ERROR: Failed to determine docker network subnet"
    exit 1
fi

sudo iptables -t nat -A POSTROUTING -s ${subnet} ! -o ${bridge} -j SNAT --to-source ${source_address}

Verify

$ sh create_docker_network.sh -i lo0 -n loopnet
98fe05b4f2047d3ea1f98fa6be1a9a80f7c9c052d4bbf20431a8555d6e1799e6
$
$ docker run --rm --network loopnet alpine:latest ping 1.1.1.3
PING 1.1.1.3 (1.1.1.3) 56(84) bytes of data.
64 bytes from 1.1.1.3: icmp_seq=1 ttl=62 time=6.98 ms
64 bytes from 1.1.1.3: icmp_seq=2 ttl=62 time=7.78 ms
64 bytes from 1.1.1.3: icmp_seq=3 ttl=62 time=6.57 ms
^C
$
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment