Isolating interfaces using network namespaces

Hi.

I have the following solution where one wireless interface is on the host and the other is in the network namespace.

root@OpenWrt:~# ip link
6: wg: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/none 
43: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1280 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 7e:ea:9e:65:22:46 brd ff:ff:ff:ff:ff:ff

root@OpenWrt:~# ip -netns vpn link
3: wlan1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DORMANT group default qlen 1000
    link/ether cd:fa:df:33:eb:48 brd ff:ff:ff:ff:ff:ff permaddr fb:ab:6b:f8:0b:3a

wlan0 is used as the access point and wlan1 is used as the station.
The wg interface is a Wireguard VPN that is linked to the network namespace.

But it does not work out-of-the-box and requires some customization (e.g. installing the ip-tiny package, disabling some services and executing additional commands).

For example, WiFi and wpad must be disabled (otherwise it won't work properly).

root@OpenWrt:~# wifi down
root@OpenWrt:~# service wpad stop

Then create a network namespace.

root@OpenWrt:~# ip netns add vpn

Create wireguard and configure it.

root@OpenWrt:~# ip -netns vpn link add wg type wireguard
root@OpenWrt:~# ip -netns vpn link set wg netns 1
root@OpenWrt:~# wg setconf wg /etc/wg.conf
root@OpenWrt:~# ip -4 address add .../32 dev wg
root@OpenWrt:~# ip -6 address add .../128 dev wg
root@OpenWrt:~# ip link set wg up

Configure the `station' using one of the wireless interfaces.

root@OpenWrt:~# iw phy phy1 set netns name vpn
root@OpenWrt:~# ip netns exec vpn iw phy phy1 interface add wlan1 type managed
root@OpenWrt:~# ip netns exec vpn wpa_supplicant -i wlan1 -c /etc/wpa_supplicant.conf -B
root@OpenWrt:~# ip netns exec vpn udhcpc -i wlan1 -b

Now configure the `access point' using the second wireless interface.

root@OpenWrt:~# iw phy phy0 interface add wlan0 type managed
root@OpenWrt:~# hostapd -i wlan0 /etc/hostapd.conf

Be aware that this is not a step-by-step instruction. It lacks some steps.

When all these steps are completed, clients can connect to the access point placed on interface wlan0, and the router itself is connected to the public network using a station on interface wlan1, with all traffic encrypted by Wireguard.

But that means that there is no longer a way to configure WiFi with /etc/config/wireless.
And a bunch of commands have to be run to configure all that.
There is no WAN / LAN configuration yet, but it will be implemented the same way, and /etc/config/network will probably be useless for WAN as well.

So my question is what is the proper way to implement this in OpenWrt using standard utilities / scripts / configurations?

Or there is no easy way to do it and I need to write my own scripts handling all settings using ip / iw utilities and configurations such as hostapd.conf and dnsmasq.conf?

Thanks.

There is no implementation for instantiating common network services. Without namespaces too

I don’t know what network name spaces are, but would a VLAN accomplish the same?

I don't think so, but I could be wrong.
You can read more about network namespaces here - https://www.wireguard.com/netns/

OpenWrt uses UCI for configuration.

Do you want me to implement this as part of UCI in OpenWrt?
I don't think many people would be interested in something like this to make it worth implementing.
And I'm not that familiar with the OpenWrt codebase, so it would take some time (probably a lot) to make it usable...
And to be honest I don't really know how it should look like as a UCI configuration.

I wasn't specifically suggesting anything about new implementations. My comment was just answering your question about the proper way to implement configurations.

Like @darksky , I'm also not really sure how namespaces would apply to OpenWrt and why someone would use them instead of subnets/VLANs which are well documented and proven on the platform.

If you want to chase down the namespaces thing, you're welcome to implement whatever you'd like.

Yeah, I doubt it would be worthwhile... AFAIK, you're the only one talking about namespaces like this. But if you think there's value to doing this, by all means feel free to experiment.

My suggestion would be to look at the methods of setting up multiple subnets/VLANs first. If those have specific shortcomings that your namespaces method can better accommodate, then it could be worth the effort involved.

Nor do I. But you're talking about something that doesn't really exist in OpenWrt now, so you'd probably need to work out the full context of how it would be implemented here. But I think you'll find that subnets/VLANs achieve the same goal.

One of the use cases for network namespaces: https://www.redhat.com/en/blog/net-namespaces

It looks interesting, but in my quick scan of that article, I don't really see what is fundamentally different wrt VLANs/subnetting in terms of the ultimate behaviors of the system. Obviously the implementation is different, but it seems like the end result is the same, no? Am I missing something?

With just vlans and all its directly reachable networks you have no isolation between the networks and sometimea not even an isolation between the host and the virtual network.
With a namespace you can restrict a service or a container very tightly.

But you will find network namespaces more in server hosting a bunch of different stuff.
Besides namespaces there are also virtual routing functions to have fine granular routing rules between certain networks, namespaces and there attached interfaces.

The main reason I use network namespaces is because it's a fairly simple solution to separate the physical interfaces (which are connected directly to the Internet) from the entire system.
This way, any application on the system only uses the Wireguard interface and nothing else.
I've been using this solution for over 7 years on desktop Linux, and it has never failed me.

For me, this is much easier than dealing with routing & firewall to prevent traffic leaks (I've had bad experiences).
I can't say anything about subnets/VLANs. Never thought about using them in that way.

In Linux it's quite easy to implement. 1-2 scripts, and everything is ready.
But it's not the case with OpenWrt because of heavy integration with UCI.

I have already made it work manually on OpenWrt, but I need it to work automatically.
That's why I asked about the easiest way to implement it or some recommendations.

At this point, I'm thinking of disabling all network/wireless services and just writing some scripts to configure it on boot up the way I want it.
Probably a bad idea, but if it works, why not?
Unless someone can suggest something more proper....

With UCI, it's not clear how to handle interfaces created inside network namespaces and interfaces that have moved inside that namespace.

Perhaps something like this would work:

config namespace
    list namespace 'vpn'

config interface 'wireguard'
    option device 'wg0'
    option namespace 'vpn'
    option bind_ns '1'

config interface 'wireless'
    option device 'wlan0'
    option bind_ns 'vpn'

Where option namespace 'vpn' means Create this interface in the 'vpn' namespace, and option bind_ns '1|vpn' means Move this interface to namespace '1' or 'vpn'.
But there may be other use cases that are not compatible with this example.
And I'm not sure that its implementation would be possible without making changes to netifd.

Nope, netns is isolated network stack, with own routes ip addressing etc. Like network part of docker container. Thought that one gets linked to host in the end.

Is it possible to create the namespace with an interface hook script and then move the interface to that namespace?
But maybe then some UCI things will break. So you might are better suited to create the ns and wg manually... But network namespace integration in UCI would be nice.

Some things will definitely break.
For example, iw list will see interface phy0 but not phy1 after moving it into the namespace.
But ip netns exec vpn iw list will show it.... Without phy0, of course.

Hmmm, didn't see that in the documentation...

Wouldn't this be handled traditionally by means of the firewall? I do get that namespaces would be an alternate method (and maybe less to explicitly configure and/or easier to read at a human level??), but does the firewall (and general routing engine) lack features that are enabled by the use of namespaces?

Alternatively, would this allow the isolation of devices on the same subnet when implemented at the router (assuming all devices must traverse the router). That is to say, would this be capable of firewall type actions at L2??

Enabled - yes (docke4 lxc use them) instrumented in luci - nope.

Could for instance have seperated physical or virtual interfaces and they all live in there own little universe without any interaction if you like.
I only used them at work were we wanted to sperate external clients or even different in house teams.
Yes, docker and lxc are famous users of different kind of namespaces.
I still thinking of use cases on a home router besides that von interface scenario from this thread.

killing hardware offload and related pergormance gains among those.