The reason it does not work when you have both an active Ethernet and 4G connection is that traffic is getting routed through the Ethernet connection while you’re masquerading on the cellular interface.
NetworkManager is using it’s default routing priorities which is to favor Ethernet over wireless over cellular. Your script first checks for an IPv4 network on the cellular interface and, if found, masquerades on that interface regardless on whether or not there are other active networks with greater routing priorities.
I’d be inclined to masquerade on the hotspot network (which will almost certainly be 10.42.0.0/24) rather than by interface as it’s a single masquerade rule which will cover any active interface and will also handle, a little better, changing routes due to interfaces coming up and down.
I also think that the logic determining which, if any, WAN interface to use could be greatly simplified by looking at routes rather than links and/or addresses, assuming the default share network address of 10.42.0.0/24
is used for hotspots…
# pseudo-code
if [ ! -z "$(ip r | grep ^default)" ]
then
sudo sysctl net.ipv4.ip_forward=1
sudo iptables-legacy -t nat -A POSTROUTING -s 10.42.0.0/24 ! -d 10.42.0.0/24 -j MASQUERADE
# anything else required when bringing up hotspot
else
# no IPv4 routes available
fi
Essentially, if there is a default route then masquerade, ip r
only lists IPv4 routes.
And if you need to get the current interface serving the default route…
dev_net_wan=$(ip r | grep ^default | awk '{print $5}')
Is it required to enable forwarding? I know that standard connection sharing does not work out the box on the Librem 5. However, after creating a shared connection on other interfaces all that is needed is the masquerade rule. I haven’t looked much into it but it did occur to me that perhaps it fails because NetworkManager is calling out to iptables rather than iptables-legacy for the masquerade rule? If that were the case, NetworkManager will already be enabling forwarding when you activate the hotspot.
You might want to consider some clean up on error rather than simply exiting. For example…
To get here, you have first enabled IPv4 forwarding, so if it errors now, the script exits with no masquerade rule and leaving forwarding enabled?