Use ipsets in nat rules?

I need to masquerade a set of IP addresses when they try to reach a certain (internal) IP address on another VLAN.

I found no way to do this in Luci and my attempts with /etc/firewall.user have failed:

nft add rule nat postrouting ip saddr @lgcastdevices ip daddr 10.1.103.102 masquerade

When I do a service firewall restart the answer is

Error: No such file or directory
add rule nat postrouting ip saddr @lgcastdevices ip daddr 10.1.103.102 masquerade
         ^^^
Include '/etc/firewall.user' failed with exit code 1

Is there a way to use an ipset for masquerading or do I have to create a rule for every single IP?

Thanks!

You would create an SNAT - this can be done on LuCI under the "NAT Rules" tab under the Firewall. This is just an example:

config nat                    
        option src '<other_vlan>' #<--"Outbound Zone" in LuCI
        option name 'other_vlan_nat'
        option family 'ipv4'
        option proto 'all'
        option src_ip '192.168.1.xxx/24'
        option target 'SNAT'            
        option snat_ip '<IP_to_use>'

You can also set masquerade in the firewall and specify a specific IP. That can be edited on LuCI under each Firewall Zone's Advanced Settings.

I could maybe masquerade the whole subnet (thanks!), but at the moment I am trying to masquerade only the addresses in an ipset.

Do you know whether that can be done?

I just added that:

You can also set the inverse:

screen624

It seems you desire to enable masquerading on the DST Zone and configure the "Restrict Masquerading to given source subnets" section.

Can you explain how this IP set is obtained/populates and how it contains destination subnets?

This seems like a routing protocol of some kind. I apologize for overlooking this point.

Ah, I think I see what you mean, the problem is that the subnets are in different firewall zones.

Why I need masquerade:

My TV (LG) is in a different VLAN than my/our phones. I can see the TV and send packages to it (all from the phone), but I can't cast to it because the TV itself rejects packets that come from another subnet (403 Forbidden). Everything works when I masquerade the phones IP addresses.

I created an ipset in LuCI containing the IPs of the phones. I'd like to use that ipset now somehow in a rule so that these IPs get masqueraded so that the TV accepts them.

I apologize for overlooking this point.

Absolutely no need to apologize, I am happy for any help!

1 Like

OK. I'll respond like this: there's no direct method to masquerade an IP set. This is because - Your DST (i.e. the IPs in the set) must be considered before the routing decision is made (i.e. PREROUTING) - and you want this to have an effect on a POSTROUTING config (i.e. masquerading).

It should be possible to somehow mark these packets and masquerade all such packets destined for foo.

Thanks for the answer! :slight_smile:

I'll try masquerading the whole subnet then.

The problem is here. You are still thinking in terms of iptables (not helped by the very confusing use of the term "ipset" in fw4 as this implies iptables in all other Linux distros).

There is no "nat" table and postrouting chain to add your rule to, these are legacy table/chain names.

Try this instead, on the command line at first so that a reboot will clear it if something breaks:

nft insert rule inet fw4 srcnat_wan ip saddr @lgcastdevices ip daddr 10.1.103.102 masquerade

1 Like

Thanks for catching that, even after seeing nft and the user file, I saw that and thought "iptables".

An SNAT rule (in NAT rules) would be more appropriate there. It provides more granular settings compared to the MASQUERADE of the whole traffic leaving a zone.

2 Likes

Thanks! I tried it but nft says the ipset doesn't exist

The ipset exists, do I need to define it on the CLI?

I barely know what I am doing with the masquerading, so this might be a stupid question, but why would a SNAT be better? From checking it out in LuCI it seems the only additional option would be to specify the IP address?

With masquerade I masquerade a bunch of IPs only when they connect to a single IP in another subnet, not the whole source subnet?

I assumed you created it in the firewall config.

Do:
nft list ruleset

and look for something like:
set lgcastdevices { .......

It will probably be near the top somewhere.

Note that this is an nftset, not an ipset, even though fw4 calls it an ipset. This causes so much confusion....

EDIT:
Actually, I forgot it would be simpler to do:
nft list sets

root@OpenWrt:~# nft list sets
table inet fw4 {
	set piholes {
		type ipv4_addr
	}
	set ssdp_out {
		type inet_service
		size 65535
		flags dynamic,timeout
		timeout 5s
	}
}
root@OpenWrt:~#

Thanks, I guess that means I need to define it manually (not in LuCI) :slight_smile:

Which is weird, because the piholes nftset is listed, and that one is defined the same way as the lgcastdevices set

Maybe... I never use Luci so do not know... :wink:

Try:

nft add set inet fw4 lgcastdevices { type ipv4_addr\; size 16\; }
nft add element inet fw4 lgcastdevices { 192.168.178.57, 192.168.178.193, 10.1.100.30, 10.1.100.31 }
nft insert rule inet fw4 srcnat_wan ip saddr @lgcastdevices ip daddr 10.1.103.102 masquerade

Masquerade and SNAT do the same, nat the source IP of the packet.
Masquerade is more common on edge routers where you can NAT all traffic exiting an interface, using the IP address of the interface and is used when we want to alter all traffic.
SNAT is used for more refined cases, like yours, when only specific traffic needs to be translated.

2 Likes

I put those rules in /etc/firewall.user and ran service firewall restart (no errors), but the traffic isn't masqueraded.

Running tcpdump -i br-iot host 10.1.103.102 shows that the traffic isn't sent from openwrt, but from the phone sending the packets.

image

Apologies if I am still missing something obvious, but doesn't this rule mean that not all traffic is masqueraded but only traffic going to 10.1.103.102.

That would be fine for me, but I wanted to make sure that I am not misinterpreting the rule.

Well it seems my suggestions to fix the errors in your rules work. But maybe your rules do not do what you need ....