Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Setup a network namespace with Internet access
#!/usr/bin/env bash
set -x
NS="ns1"
VETH="veth1"
VPEER="vpeer1"
VETH_ADDR="10.200.1.1"
VPEER_ADDR="10.200.1.2"
if [[ $EUID -ne 0 ]]; then
echo "You must be root to run this script"
exit 1
fi
# Remove namespace if it exists.
ip netns del $NS &>/dev/null
# Create namespace
ip netns add $NS
# Create veth link.
ip link add ${VETH} type veth peer name ${VPEER}
# Add peer-1 to NS.
ip link set ${VPEER} netns $NS
# Setup IP address of ${VETH}.
ip addr add ${VETH_ADDR}/24 dev ${VETH}
ip link set ${VETH} up
# Setup IP ${VPEER}.
ip netns exec $NS ip addr add ${VPEER_ADDR}/24 dev ${VPEER}
ip netns exec $NS ip link set ${VPEER} up
ip netns exec $NS ip link set lo up
ip netns exec $NS ip route add default via ${VETH_ADDR}
# Enable IP-forwarding.
echo 1 > /proc/sys/net/ipv4/ip_forward
# Flush forward rules.
iptables -P FORWARD DROP
iptables -F FORWARD
# Flush nat rules.
iptables -t nat -F
# Enable masquerading of 10.200.1.0.
iptables -t nat -A POSTROUTING -s ${VPEER_ADDR}/24 -o eth0 -j MASQUERADE
iptables -A FORWARD -i eth0 -o ${VETH} -j ACCEPT
iptables -A FORWARD -o eth0 -i ${VETH} -j ACCEPT
# Get into namespace
ip netns exec ${NS} /bin/bash --rcfile <(echo "PS1=\"${NS}> \"")
@purpletech77

This comment has been minimized.

Copy link

commented Nov 9, 2016

Hi,
Iam able to ping the host IP with your script from ns1, but Iam not able to ping outside of the host - Any idea ?

Thanks .

@andrew160

This comment has been minimized.

Copy link

commented Nov 25, 2016

@purpletech77 Make sure you got the interface name right. For me it was enp0s3, and not eth0. Now it works perfectly 😄

@markododa

This comment has been minimized.

Copy link

commented Feb 3, 2017

if the system uses a local dns server (like dnsmasqd on ubuntu ), a resolv.conf needs to be setup for the namespace, for example
mkdir -p /etc/netns/ns1/
echo 'nameserver 8.8.8.8' > /etc/netns/ns1/resolv.conf

@EJohnF

This comment has been minimized.

Copy link

commented Feb 15, 2017

It works fine for me if change row 49:
iptables -t nat -A POSTROUTING -s ${VPEER_ADDR}/24 -o eth0 -j MASQUERADE
to
iptables -t nat -A POSTROUTING -s ${VETH_ADDR}/24 -o eth0 -j MASQUERADE

And it's logically true. In this row you set up the iptable routing. And try to connect eth0 with virtual interface.
But, VPEER_ADDR - locate in the ns1 network namespace while VETH_ADDR in global(default).

Am I right that it's a mistake in that row?

@aneeshdurg

This comment has been minimized.

Copy link

commented Sep 12, 2018

I don't think that row makes a difference, it's only looking at the prefix, right?

@mcgovern612

This comment has been minimized.

Copy link

commented Jun 26, 2019

Any ideas why I would be able to ping from the namespace, but not wget or curl?

@dpino

This comment has been minimized.

Copy link
Owner Author

commented Jun 27, 2019

Hi, sorry for not replying comments before. This is the first time I noticed there were actually comments here.

@mcgovern612 Are you pinging to an IPv4 address or to a host name? Maybe that's the issue and what's not actually working is DNS resolution (I generally ping to an IPv4 address and wget or curl an URL resource). For name host resolution check the comment by @markoda (https://gist.github.com/dpino/6c0dca1742093346461e11aa8f608a99#gistcomment-1987705) or add an external nameserver to your /etc/resolv.conf.

@dpino

This comment has been minimized.

Copy link
Owner Author

commented Jun 27, 2019

@EJohnF About line 49, I actually tried both VPEER_ADDR and VETH_ADDR and it works in both cases. That said, I think it's more correct to apply source natting in the host interface since the host interface should be reachable from the network namespace.

@dpino

This comment has been minimized.

Copy link
Owner Author

commented Jun 27, 2019

@andrew160 nice catch, the "eth0" string should be another variable in the script.

@mcgovern612

This comment has been minimized.

Copy link

commented Jun 27, 2019

@dpino DNS is working as ping can resolve hostnames, and in wget calls I can see resolution but it just doesn't connect.

I must say though, thank you for the awesome script and blog description. It was very useful for someone who has never used network namespaces.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.