2

I have an IP address on my server, say, 192.168.0.3, I want to share in a net namespace, so to run apps there which will only be able to communicate to the internet using that 192.168.0.3.

I can "kind" of get it working with the macvlan device type... except, for having two mac addresses, the gateway will often favor my root or my namespace-bound interface.

Is there a way I could just mirror that IP inside a netns without affecting the external IP?

Here's what I've been trying:

ip netns add myns
ip link add link eth0 name en0 netns myns type macvlan
ip netns exec myns ip link set en0 up
ip netns exec myns ip addr add 192.168.0.3/24 dev en0
ip netns exec myns ip route add default via 192.168.0.1

And then I test with variations of netcat; either listening in a remote host and connecting from inside and outside the namespace, or listening inside and outside the namespace and connecting from the remote host.

With macvlan it is unreliable just because the immediate router will send packets to a mac address or the other, I need to reset the cached mac in the router (by sending a packet) before I can switch between the physical or macvlan interface. While this is understandable, I am missing a way to let the IPs be "shared" instead of "fought over".

My motivation for that is that I have just a few IPs in my server, and each already listen to services (that properly allows you to bind to specific IP/ports). And then I'm trying to create a chroot jail which would expose only one of these few IPs to apps running therein. So these jailed apps could bind to any (free) port of these IPs, but won't stand a chance of taking over any other IP addresses in the same server.

(I can think of other options like using LD_PRELOAD, or iptables NAT, but I really think I'm missing just a little to have it working with net namespaces)

Avenger
  • 21
  • 2
  • If by "share" you mean the host has the same IP address as the network namespace, then you're just causing a collision by using the same IP address on two systems (consider the network namespace as an other system). Looks like an XY problem with a wrong Y part. You'll have to explain better X: the need to have applications use a specific IP address and why their configuration isn't enough. – A.B Mar 15 '23 at 23:50
  • Yes, I understand this is making a collision, and that's exactly why sometimes it works within the netns and then outside it. What I needed was a means to literally expose the outside .3 IP in the netns, such that apps within it could only bind to it. – Avenger Mar 22 '23 at 19:13

1 Answers1

1

You have two options:

  • Give the IP address 192.168.0.3 to an interface in that namespace, and don't use it outside of that namespace. This will allow that namespace to use the full range of ports without fear of collisions. For this, macvlan is a good option.
  • Share the IP address 192.168.0.3 between the host and the namespace. In this case, it has to be the same interface, you can't have separate interfaces using the same IP address on the same network. A solution for this would be to use a veth pair and set up forwarding on the host (making sure to use the correct interface/source address). This is similar to what containers do. That would NOT allow you to run a webserver on port 80 on both the host and the container though.

You can set up the veth pair like this:

# Create namespace
ip netns add myns
ip -n myns link set lo up
# Create devices
ip link add myveth0 type veth peer name myveth1
ip link set myveth0 netns myns
# Set addresses
ip -n myns addr add 10.64.0.1/24 dev myveth0
ip -n myns link set myveth0 up
ip addr add 10.64.0.2/24 dev myveth1
ip link set myveth1 up
# Enable forwarding between netns and outside network (customize the rules as needed)
sysctl -w net.ipv4.ip_forward=1
iptables -t filter -A FORWARD -i myveth1 -j ACCEPT
iptables -t filter -A FORWARD -o myveth1 -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.64.0.0/24 -j MASQUERADE
remram
  • 111
  • 5
  • Your second option is exactly what I wanted to do but couldn't find a way to. The first option you mentioned is what I am able to do but can't, because I already use the IP outside the netns. I just wanted to use the netns like a "mask" to expose only a range (or a single) IP address I have outside. I don't understand what you mean with _"use a veth pair and set up forwarding"_, at first it sounds exactly what I want to avoid (different IPs within the netns). – Avenger Mar 22 '23 at 19:10
  • Sure, I added instructions for that. This will create a private interface with a private IP address in the namespace. Then you can forward packets on the host between the namespace and the outside network, using whatever routing and filtering rules you need. The problem w.r.t your initial request is that the namespace sees that private IP address, not `192.168.0.3`. – remram Mar 23 '23 at 20:31
  • Thanks for sharing the alternative. This is exactly what I meant with _iptables NAT_ and _conceptually_ what Docker containers do to make services accessible from outside. I'm actually using the `LD_PRELOAD` alternative but still looking forward to a possibility to just use the same IP through different namespaces, if that's possible somehow. – Avenger Mar 24 '23 at 21:30
  • Same address in different namespaces... why not just use a single namespace for all your jails? What are you namespacing? They have to share a single namespace of UDP and TCP ports if they use the same IP address, because of how those protocols work. – remram Mar 25 '23 at 21:29
  • Because I need 192.168.0.3 also to programs outside the netns, that could bind to that IP and (hypotetically) another 192.168.0.2 address -- that I don't want jailed apps to be able to see or bind to. And I'll still want to get "address already in use" in case, from either netns, I try to bind to an already used port. That's a problem the iptables solution can't solve (yet the `LD_PRELOAD` one does). – Avenger Apr 01 '23 at 16:33