Force new process to use the specific network interface (using netns/network namespaces)

Solution 1:

It seems to work with the following script. An extra feature that was not present in my original question is how to keep the interface in both main and new namespaces (but I will deal with that later). Following is quite descriptive solution based on the information provided in: here, here, here, here, here and here.

# Save default settings to files for a handy reference
ip addr > log_000.ip_addr.txt
ip link > log_000.ip_link.txt
ip route > log_000.ip_route.txt
route -n > log_000.route_n.txt

# Interfaces
INTERFACE_0="usb0"
INTERFACE_1="enx0c5b8f279a64"

# Collect information on current configuration
PUBL_IP=$(curl --silent ifconfig.me/ip)
INTERFACE_0_PUBL_IP=$(curl --silent --interface ${INTERFACE_0} ifconfig.me/ip)
INTERFACE_1_PUBL_IP=$(curl --silent --interface ${INTERFACE_1} ifconfig.me/ip)

INTERFACE_0_PRIV_IP=$(ip a show ${INTERFACE_0} | awk '/inet / {print $2}')
INTERFACE_1_PRIV_IP=$(ip a show ${INTERFACE_1} | awk '/inet / {print $2}')

INTERFACE_0_GATE=$(ip route show dev ${INTERFACE_0} | awk '/default via/ {print $3}')
INTERFACE_1_GATE=$(ip route show dev ${INTERFACE_1} | awk '/default via/ {print $3}')

echo "" > log_001.IPs.txt
echo "PUBL_IP: ${PUBL_IP}"                          >> log_001.IPs.txt
echo "============================================" >> log_001.IPs.txt
echo "INTERFACE_0_PUBL_IP: ${INTERFACE_0_PUBL_IP}"  >> log_001.IPs.txt
echo "INTERFACE_0_PRIV_IP: ${INTERFACE_0_PRIV_IP}"  >> log_001.IPs.txt
echo "INTERFACE_0_GATE: ${INTERFACE_0_GATE}"        >> log_001.IPs.txt
echo "============================================" >> log_001.IPs.txt
echo "INTERFACE_1_PUBL_IP: ${INTERFACE_1_PUBL_IP}"  >> log_001.IPs.txt
echo "INTERFACE_1_PRIV_IP: ${INTERFACE_1_PRIV_IP}"  >> log_001.IPs.txt
echo "INTERFACE_1_GATE: ${INTERFACE_1_GATE}"        >> log_001.IPs.txt
cat log_001.IPs.txt

NAMESPACE_1="ns1"

# SETUP: Create new namespace.
sudo ip netns add ${NAMESPACE_1}

# CHECKUP: Verify that the namesapce was created.
sudo ip netns list

# CHECKUP: List interfaces in the main and new namespace
ip addr show
sudo ip netns exec ${NAMESPACE_1} ip addr show

# SETUP: Link (move) interface to namespace.
# NB this interface will not be availabie in the main (default) namespace anymoe.
sudo ip link set ${INTERFACE_1} netns ${NAMESPACE_1}

# CHECKUP: verify that the interface was moved from main to new namespace.
ip addr show
sudo ip netns exec ${NAMESPACE_1} ip addr show

# SETUP: Set interface IP address in new namespace and bring it up.
# TODO: Check it the address must be the as it was in the main namespace.
sudo ip netns exec ${NAMESPACE_1} ifconfig ${INTERFACE_1} ${INTERFACE_1_PRIV_IP} up

# SETUP: Bring up the loopback interface (as it may be needed by processes run in new namespace).
sudo ip netns exec ${NAMESPACE_1} ifconfig lo 127.0.0.1/8 up

# CHECKUP: List interfaces (loopback and INTERFACE_1) in the new namespace
sudo ip netns exec ${NAMESPACE_1} ip addr show

# CHECKUP: Verify route table.
sudo ip netns exec ${NAMESPACE_1} route -n

# SETUP: Add default gateway to route in new namespace.
sudo ip netns exec ${NAMESPACE_1} route add default gw 192.168.7.1

# CHECKUP: Verify route table again.
sudo ip netns exec ${NAMESPACE_1} route -n

# DONE: Use new namesapce.
sudo ip netns exec ${NAMESPACE_1} ping 8.8.8.8
sudo ip netns exec ${NAMESPACE_1} traceroute 8.8.8.8

# SETUP: Fix DNS
sudo mkdir -pv /etc/netns/${NAMESPACE_1}
sudo echo "nameserver 8.8.8.8" > /etc/netns/${NAMESPACE_1}/resolv.conf


sudo ip netns exec ${NAMESPACE_1} curl ifconfig.me/ip
sudo ip netns exec ${NAMESPACE_1} curl --silent ifconfig.me/ip

# EXTRA: Undo changes (revert to the original state of IP settings)
sudo ip netns del ${NAMESPACE_1}