Ubus/uci getting devices in the wan zone

Hi, how can I extract a list of interfaces in the wan zone?

Assume I have this in the config:

config zone
        option name 'wan'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option masq '1'
        option mtu_fix '1'
        list network 'wan'
        list network 'wan6'
        list network 'test'

So I basically want to get a list consisting of "wan wan6 test".

So far I've come up with this:
ubus call uci get '{ "config": "firewall", "type": "zone" }'
Which produces this result:

Summary
{
        "values": {
                "cfg02dc81": {
                        ".anonymous": true,
                        ".type": "zone",
                        ".name": "cfg02dc81",
                        ".index": 1,
                        "name": "lan",
                        "network": [
                                "lan"
                        ],
                        "input": "ACCEPT",
                        "output": "ACCEPT",
                        "forward": "ACCEPT"
                },
                "cfg03dc81": {
                        ".anonymous": true,
                        ".type": "zone",
                        ".name": "cfg03dc81",
                        ".index": 2,
                        "name": "wan",
                        "input": "REJECT",
                        "output": "ACCEPT",
                        "forward": "REJECT",
                        "masq": "1",
                        "mtu_fix": "1",
                        "network": [
                                "wan",
                                "wan6",
                                "test"
                        ]
                }
        }
}

Now how to narrow it down to specifically the wan zone, and then how to get the interfaces out of it? I suppose something like jsonfilter should do it, but maybe I can query for the specific info directly? If I need to use jsonfilter then maybe someone can throw the exact command at me? Probably noob questions, sorry about that :slight_smile:

When querying the firewall, all that will show up will be the wan network interface.

What exactly are you trying to find? The device/port in the router itself that is used for the wan network interface? Or something else?

if [ -x /sbin/fw4 ]; then
    devices=$(fw4 zone wan)
elif [ -x /sbin/fw3 ]; then
    devices=$(fw3 zone wan)
else
    # no uci firewall present, /etc/config/firewall is meaningless
fi
1 Like

I want to add firewall rules which apply specifically to the devices which belong to the wan zone. I don't want to assume that the user has a standard config, so my idea is to query the firewall config, get the wan interfaces, then get the devices out of that.

In the latter case, when no uci firewall is present, you might want to fall back to sourcing /lib/functions/network.sh and using network_find_wan plus network_get_device for an educated guess.

1 Like

The wan zone, and by extension the upstream network, is typically facing the internet. As such, the wan zone treats its associated network(s) as untrusted and has a default config that rejects all unsolicited input from those network(s) - meaning that no unsolicited traffic can ingress to the router and the networks behind the router from the wan.

So what additional firewall rules are you looking to implement?

In some cases, people use a setup where certain connections are allowed to pass from the wan into lan. For example, if running an application which needs to be accessible from the internet. I'm developing a project which limits allowed connections based on geoip. Similar to a part of BanIP functionality, but (for now) focusing specifically on geoip.

My understanding is that @antonk is looking for a set of robust heuristics to figure out the effective wan (untrusted upstream) network interfaces on a given OpenWrt system without having to hardcode “wan” in his custom software. Querying the members of the “wan” firewall zone would be one possibility.

Of course there can be configs where the upstream interfaces are neither called “wan” nor part of a firewall zone called “wan” but users running such a config are likely used to the fact that they have to tune the default config of most software assuming a “wan” interface.

2 Likes

That all makes sense... I was asking because the OP was specifically probing the wan firewall zone which will only result in the discovery of the network interfaces (or tunnel devices) associated with that zone. It wasn't clear from the OPs initial description exactly what they were hoping to probe and why.

This, of course, I know. It wasn't initially clear that you were specifically allowing said connections, and what 'devices' you were trying to probe (i.e. 'what is the upstream network/device on this local router' vs 'what are the L2 neighbors on the upstream network' vs 'what/who are the hosts that are originating a connection request into my network.'

This makes a lot more sense now. Thanks for describing. My original reason for asking was simple -- sometimes people assume they need to further harden the firewall from a near-default installation. In these cases, it's often necessary to identify the intent of their additional hardening requests (which are often already satisfied by the default wan zone ruleset). Your case is clearly quite different.... sounds like a cool project. Sorry if I have caused any distraction with respect to the information you were requesting.

It's all good, indeed my wording wasn't specific enough. Thank you for your kind help.

1 Like

Eventually I've come up with this code (it uses a couple of custom functions but their names should be self-explanatory):

detect_wan() {
	wan_devices=''
	checkutil ubus && { # for OpenWRT
		if [ -x /sbin/fw4 ]; then
			wan_devices="$(fw4 zone wan)"
		elif [ -x /sbin/fw3 ]; then
			wan_devices="$(fw3 zone wan)"
		fi
	}
	# fallback and non-OpenWRT
	[ ! "$wan_devices" ] && wan_devices="$({ ip r get 1; ip -6 r get 1::; } 2>/dev/null |
		sed 's/.*[[:space:]]dev[[:space:]][[:space:]]*//;s/[[:space:]].*//')"
	sanitize_str wan_devices
}

Since I need a fallback for non-OpenWRT systems anyway, I think I can fall back to the same code in OpenWRT systems which for some reason don't have fw4 or fw3 installed.

You can save two bytes: wan_devices= or improve the code with local wan_devices.

I'm not sure if it's safe/predictable for ash, I'd do [ -z "$wan_devices" ].

Yes, I'm aware of that but I don't mind giving 2 bytes for clarity :slight_smile:

This definitely does work on ash, as well as on dash and bash. This is also posix'ly correct, although the documentation warns about incompatibility with historical systems.
image

image

https://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.