With some help from the answers by @Irfan Latif linked in the comment and here, and by examining the output of iptables -L
and iptables -t nat -L
in various scenarios like Hotspot, BT tethering, USB tethering etc., I managed to write a script that helps me to share my mobile data connection to the local Wi-Fi network by using a static IP for the phone, and setting it as the gateway in the Wi-Fi router or in individual devices.
Here is the script I wrote, it must be run in a root shell or by prefixing su -c
:
#!/bin/sh
echo "(Re-)creating iptables NAT and Forward rules..."
for i in 0 1 2 3 4 5 6 7 8 9 10 ; do
iptables -t nat -D POSTROUTING -o rmnet_data$i -j MASQUERADE
iptables -t nat -I POSTROUTING -o rmnet_data$i -j MASQUERADE
iptables -D FORWARD -i rmnet_data$i -o wlan0 -m state --state RELATED,ESTABLISHED
iptables -D FORWARD -i rmnet_data$i -o wlan0 -j ACCEPT
iptables -D FORWARD -i wlan0 -o rmnet_data$i -j ACCEPT
#iptables -D FORWARD -i wlan0 -o rmnet_data$i -m state --state INVALID -j DROP
iptables -I FORWARD -i rmnet_data$i -o wlan0 -m state --state RELATED,ESTABLISHED
iptables -I FORWARD -i rmnet_data$i -o wlan0 -j ACCEPT
iptables -I FORWARD -i wlan0 -o rmnet_data$i -j ACCEPT
#iptables -I FORWARD -i wlan0 -o rmnet_data$i -m state --state INVALID -j DROP
done
echo "Enabling forwarding for wlan and rmnet_data interfaces..."
echo 1 >/proc/sys/net/ipv4/conf/wlan0/forwarding
echo 1 >/proc/sys/net/ipv6/conf/wlan0/forwarding
for i in 0 1 2 3 4 5 6 7 8 9 10 ; do
echo 1 >/proc/sys/net/ipv4/conf/rmnet_data$i/forwarding
echo 1 >/proc/sys/net/ipv6/conf/rmnet_data$i/forwarding
done
echo "Emptying the main route table..."
ip route flush table main
echo "Copying rmnet_data interface routes to main table..."
IFS=$'\n'; for i in $(
ip route show table all |
grep "table rmnet_data" |
grep -v "expires" |
sed -Er 's/table rmnet_data[0-9]* /table main /g'
); do
eval "ip route add $i"
done
echo "Copying wifi interface routes to main table (except default)..."
ip route del default table wlan0
IFS=$'\n'; for i in $( ip route show table wlan0 | grep -vE 'expires|default' ); do
eval "ip route add $i table main"
done
echo "Replacing lookup routes for main table..."
while ip rule del from all lookup main ; do "" ; done 2>/dev/null
ip rule add lookup main
echo "Clearing routing cache..."
ip route flush cache
(I don't usually write shell scripts, so some things might not be the best here 🙃)
Some notes and assumptions:
I have only tested this on a rooted Android 10 phone running MIUI 12, not sure if it works for others.
In the Developer options of the phone, I have the Mobile data always active setting switched on, to prevent turning off mobile data when Wi-Fi is connected.
I've written the script such that I am also able to continue accessing devices on the local Wi-Fi network while acting as a gateway. The icon in the status bar might wrongly indicate that Wi-Fi is being used for internet, however it can be verified in a browser, that mobile data is being used for internet.
The changes done by this script are not permanent. When Wi-Fi or mobile data disconnects or if USB tethering / Wi-Fi hotspot / BT tethering is toggled, some of the above changes are removed by Android and the script has to be run again. This can be automated using apps like Automate / Tasker. 😉
Mobile data interfaces: In the output of ip addr
, I see that my (dual-SIM Qualcomm modem) phone has 11 interfaces named rmnet_data0..10
and 9 interfaces named r_rmnet_data0..8
. I wasn't sure which one is responsible for mobile data. On toggling airplane mode on/off multiple times, I saw that r_rmnet_data
never gets assigned an address but the phone randomly picks 2 interfaces from the 11 rmnet_data
interfaces and assigns an IPv4 and v6 address to them (I guess SIM 1 uses the first 5, and SIM 2 uses the rest 5 but I'm not sure).
For the sake of simplicity, I decided to enable forwarding for all the interfaces. The names of interfaces might vary for different devices, so the for
loops in the above script will need to be adjusted/removed accordingly.
The name of the Wi-Fi interface was wlan0
on my phone. It might be different for others, and hence will need to be adjusted in the above script.
Wrong data usage counters: The data usage counters in Android settings might not show any account of the mobile data used by Wi-Fi devices in this manner, or the total data usage counter might not match with the sum of data usage counts of all apps. I believe this can be fixed by using the tetherctrl_FORWARD
chain instead of FORWARD
to make it count this usage as mobile hotspots, but am yet to try this out.
Although I have enabled forwarding for IPv6 in the above script, I have not been able to find out how to either propogate the delegated prefix to devices on the local Wi-Fi network or use the phone as an IPv6 NAT gateway (not even sure if Android supports this). I'm currently happy with just IPv4, so I might not update the script for IPv6, unless someone is interested (comment please).
Battery drain: The battery of the phone drains considerably when using it as a gateway with the above script, just as it does while using Wi-Fi hotspot.
ip
andiptables
commands). I've used my Android device for years this way to avoid the burden of hotspot on battery life.