Latest / Linux Server Admin with Fexingo: Sysadmin, Bash, and Server Engineering / How to Use Linux Namespaces for Network Isolation
Transcript
- Lucas: So you've got a legacy monitoring agent, vendor-supplied, no source access, and it insists on binding to port 8080 on all interfaces. But your production web server is already on 8080. Classic collision. Luna: Right, and you can't containerize it because it assumes it owns the whole filesystem — it writes logs to /var/log and expects a specific init system. Lucas: Exactly. You could fight with Docker and bind mounts, but there's a lighter-weight solution built right into the Linux kernel that often gets overlooked: network namespaces. Luna: Network namespaces. People hear 'namespace' and think containers, but you can use them standalone. Lucas: A network namespace is essentially a full copy of the network stack — its own interfaces, routing tables, firewall rules, and even its own /proc/net. You can run a process inside one, and it sees only the virtual Ethernet cable you give it. Luna: So the monitoring agent thinks it's on a clean machine. Lucas: It does. And the rest of your server continues using the default namespace, completely unbothered. Let's walk through it. First, create the namespace: ip netns add monitor-ns. That's it. Luna: And then you need a virtual Ethernet cable to connect that namespace to the host network, right? Lucas: Yes. You create a virtual Ethernet pair with ip link add veth-mon type veth peer name veth-host. That gives you two virtual interfaces — one you move into the namespace, one stays on the host. Luna: Move the peer in: ip link set veth-mon netns monitor-ns. Lucas: Precisely. Then you assign IP addresses. Inside the namespace: ip netns exec monitor-ns ip addr add 10.0.0.2/24 dev veth-mon. On the host side: ip addr add 10.0.0.1/24 dev veth-host. Bring both up. Luna: Now the namespace has a link to the host, but it can't reach the internet unless you set up NAT and forwarding. Lucas: Right. First enable IP forwarding on the host: sysctl net.ipv4.ip_forward=1. Then add a masquerade rule in iptables: iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE. Luna: And you need to tell the namespace to use the host-side veth as its default gateway. Lucas: Exactly: ip netns exec monitor-ns ip route add default via 10.0.0.1. Now any process inside that namespace can reach the outside world, but its network is completely isolated from the default namespace's ports. Luna: So the monitoring agent can listen on port 8080 inside the namespace, and it won't conflict with anything on the host. Lucas: That's the whole point. You start the agent with ip netns exec monitor-ns /usr/local/bin/monitor-agent. It binds to 8080 inside the namespace — the host's port 8080 remains free. And if the agent needs to talk to a remote collector, it goes through the veth pair, gets NATed, and out. Luna: What about DNS? The namespace doesn't inherit /etc/resolv.conf automatically. Lucas: Good catch. You can either copy the host's resolv.conf into the namespace's /etc/netns/monitor-ns/resolv.conf, or you can bind-mount it. I prefer copying so changes to the host don't silently affect the namespace. Luna: And debugging? How do you check what's happening inside without running a full process? Lucas: nsenter is your friend. nsenter -t <PID> -n -- curl ifconfig.me runs curl inside the same namespace as that process. Or you can use ip netns exec monitor-ns bash to drop into a shell inside the namespace. Luna: One gotcha: systemd and network namespaces don't always get along. If the process is managed by a systemd service, the namespace needs to be set up before the service starts. Lucas: You can create a systemd service that runs ip netns exec, or use the NetworkNamespace= directive in the service unit. But be careful — systemd's handling of namespace cleanup can leave stale interfaces if the service crashes. Luna: We've been talking about a specific use case, but this pattern applies beyond legacy agents. Any untrusted process — a user-facing script, a VPN client, a test instance of a database — can be isolated. Lucas: And the overhead is near zero. No daemon, no image pulls, no layered filesystem. It's just kernel objects. You can spin up a hundred of these on a single machine. Luna: Let's take a quick step back — this kind of practical, no-frills approach is exactly why we keep Fexingo ad-free. We don't want to pitch you server monitoring tools or cloud credits. If this conversation gave you something usable, and you want to support that approach, there's a link at buy me a coffee dot com slash fexingo. Lucas: Yeah, it's a small gesture that keeps the show independent. No strings, no perks. Just helps us keep doing episodes like this one. Luna: Alright, back to namespaces. There's a subtle issue: by default, the namespace gets a loopback interface, but it's down. You have to bring it up with ip netns exec monitor-ns ip link set lo up, or some processes will fail on localhost connections. Lucas: Good point. And if you need the namespace to be reachable from the outside — say, for a webhook — you can add a DNAT rule: iptables -t nat -A PREROUTING -d <host-ip> -p tcp --dport 9090 -j DNAT --to-destination 10.0.0.2:8080. Luna: So inbound traffic to host port 9090 gets forwarded to the agent's port 8080 inside the namespace. Lucas: Exactly. And you can also use a bridge instead of a simple veth pair if you want multiple namespaces to talk to each other. Create a bridge, attach the host-side veth to it, and assign IPs from the same subnet. Luna: That's more advanced, but it's the same building blocks. Namespaces, veth pairs, bridges, iptables. Lucas: Let's talk cleanup. When you're done, delete the namespace with ip netns del monitor-ns. That removes the veth pair and all routing rules. But note: if a process is still running inside, the namespace stays alive until that process exits. Luna: So you need to kill the process first, or use ip netns pids monitor-ns to find it. Lucas: Right. And one more thing — if you're using firewalld or nftables, the iptables commands won't persist across reboots. You'll want to use firewalld's rich rules or nftables sets instead. But the concept is the same. Luna: So the key takeaways: network namespaces give you process-level network isolation without containers. Five commands to set up: ip netns add, ip link add veth, ip link set, ip addr add, ip route add. And debug with nsenter. Lucas: And the whole thing runs on a stock Linux kernel — no extra packages. If you're already managing servers, this is one of the sharpest tools in the box. Luna: Next time you've got a port conflict or a trust boundary issue, try a namespace before reaching for Docker. It might save you a layer of complexity. Lucas: Exactly. And if you try it and hit a snag — DNS inside the namespace not resolving, or the interface disappearing on reboot — those are exactly the kind of edge cases we can cover in a future episode.