Score:0

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

cn flag

I have a number of interfaces available on Ubuntu 20.04 machine. Among others enx0c5b8f279a64 and usb0 with the later being used as the default one. I want to make sure that a particular process started in terminal will use only one of these interfaces (say enx0c5b8f279a64 even if the other interface is default). If this process is started and the selected enx0c5b8f279a64 inteface is down, it should not to even try to use any other interface as a fallback (as if other interfaces would not even exist from the perspective of this process).

I think that ip netns is the way to go, but I have trouble implementing any working solution. I have tried https://superuser.com/a/750412 however I am getting Destination Host Unreachable if I try to ping 8.8.8.8 :(

Relevant part of the ip a s oputput:

 9: enx0c5b8f279a64: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
     link/ether 12:12:12:12:12:12 brd ff:ff:ff:ff:ff:ff
     inet 192.168.7.100/24 brd 192.168.7.255 scope global dynamic noprefixroute enx0c5b8f279a64
        valid_lft 84611sec preferred_lft 84611sec
     inet6 2323::2323:2323:2323:2323/64 scope link noprefixroute 
        valid_lft forever preferred_lft forever
 10: usb0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000
     link/ether 34:34:34:34:34:34 brd ff:ff:ff:ff:ff:ff
     inet 192.168.42.**47**/24 brd 192.168.42.255 scope global dynamic noprefixroute usb0
        valid_lft 1858sec preferred_lft 1858sec
     inet6 4545:454:545:4545:454:5454:5454:5454/64 scope global temporary deprecated dynamic 
        valid_lft 2461sec preferred_lft 0sec
     inet6 5656:565:656:5656:5656:5656:5656:5656/64 scope global deprecated dynamic mngtmpaddr noprefixroute 
        valid_lft 2461sec preferred_lft 0sec
     inet6 6767::6767:6767:6767:6767/64 scope link noprefixroute 
        valid_lft forever preferred_lft forever

and the route table:

 route -n
 Kernel IP routing table
 Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
 0.0.0.0         192.168.7.1     0.0.0.0         UG    100    0        0 enx0c5b8f279a64
 0.0.0.0         192.168.42.129  0.0.0.0         UG    101    0        0 usb0
 192.168.7.0     0.0.0.0         255.255.255.0   U     100    0        0 enx0c5b8f279a64
 192.168.42.0    0.0.0.0         255.255.255.0   U     101    0        0 usb0

So far all the solutions that I have tried started in a similar way:

# create namespace
sudo ip netns add nspace0
# create link
sudo ip link add veth0 type veth peer name veth1
# move link
sudo ip link set veth1 netns nspace0

# DO SOME MAGIC 
# (none of the solutions that I have tried to adapt here worked for me so far).
...

# run process in namespace (here I use curl as an example) 
sudo ip netns exec nspace0 curl ifconfig.me/ip

But the problem is the MAGIC part. I have seen a number of approaches with bridges and other ip-forwarding solutions. Unfortunately none of these worked for me so far and I am not that versed in networking to be able to diagnose and fix.

Score:1
cn flag

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}
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.