[Moto E5 Guides, News, & Discussion] fddm:
This is a guide for tethering over USB Ethernet adapter. The purpose of this is to reliably USB tether to any router, without the need for a USB port or stable USB/RNDIS support(Broadcom MIPS is particularly bad). USB-OTG-ACA means the phone is powered externally while also operating in host mode. I used a cheap micro-USB Y-cable for this that lets me plug in a power source, USB Ethernet adapter, and phone together. IPv6 is supported via masquerading, so you share public IPs with your phone(thus hiding devices behind it). In this example I tether to a VPN tun0 interface, but you can tether to and from any interface you want.

This guide is targeted to more advanced users, but I included a E5 Play kernel and the files required at the bottom of this post for those who wouldn't be able to try this otherwise.

The first step is to enable the kernel IPv6 NAT table, with iptables and masquerading support. To do this I used LSM Kernel. My device is the E5 Play, steps for other devices are a little different.

https://xdaforums.com/moto-e5/development/kernel-lowspecmoto-kernel-v0-1a-t3882378

These need to be set in james_defconfig. You can also enable any necessary kernel modules for your Ethernet adapter here.

CONFIG_NF_NAT_IPV6=y
CONFIG_IP6_NF_TARGET_MASQUERADE=y
CONFIG_IP6_NF_NAT=y

I had to disable the WireGuard install script and use jury_rig.sh instead, as well as fix a minor typo in the build script(misspelled and erroneous compile command) and one of the source files (extra const declaration).

The next step is to disable the IPv4 DHCP client for the Ethernet adapter's interface eth0. After a little reverse engineering, I found this state was controlled by /data/misc/ethernet/ipconfig.txt, and there is already a tool I can use to generate configurations.

https://github.com/jhswartz/ipconfigstore

I just feed it an empty static assignment and DHCP is then disabled.

ipAssignment: STATIC
id: 0

Next was to cross-compile radvd to support RA for IPv6. Modern versions of OpenWRT support spoofing so you don't need this, but everything else requires you run a RA server from the gateway device. I needed to use android-ifaddrs to get around an unsupported feature in the NDK. The version I built expects the config to exist at /sdcard/radvd.conf.

Now comes the scripting to make everything work. I made an application for this, but you can also accomplish this with something like Tasker or even run it manually.

At boot:

*Launch radvd as a root daemon

*Start your VPN

*Delete the file /sdcard/tether.state

*Execute tether.sh as root

On Intent.ACTION_POWER_CONNECTED:

*Execute tether.sh as root

tether.state keeps the script from applying NAT rules more than once, so the connection is just restored when the script is re-ran.

#!/system/bin/sh
echo 'Waiting for tether interfaces'
for waitTime in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
do
if [ -d '/sys/class/net/eth0' ] && [ -d '/sys/class/net/tun0' ] ; then break ; fi
echo "$waitTime"
sleep 1
done
sleep 2
if [ -d '/sys/class/net/eth0' ] && [ -d '/sys/class/net/tun0' ]
then
echo 'Preparing tether interface'
ip link set dev eth0 down
ip link set dev eth0 mtu 1280
sysctl -w net.ipv6.conf.eth0.mtu=1280
sysctl -w net.ipv6.conf.eth0.autoconf=0
sysctl -w net.ipv6.conf.eth0.accept_ra=0
ip addr flush dev eth0
echo 'Setting IP addresses'
ip -6 addr add fd00::1/64 dev eth0 scope global
ndc interface setcfg eth0 192.168.42.129 24 up
echo 'Waiting for interface to come up'
for waitTime in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
do
if [ "$(cat /sys/class/net/eth0/operstate)" = 'up' ] ; then break ; fi
echo "$waitTime"
sleep 1
done
sleep 3
ip -6 route add fd00::/64 dev eth0 src fd00::1
echo 'Enabling IP forwarding'
ndc ipfwd enable tethering
echo 'Adding marked routes'
ndc network interface add 99 eth0
ndc network route add 99 eth0 192.168.42.0/24
ndc network route add 99 eth0 fd00::/64
ndc network route add 99 eth0 fe80::/64
if [ ! -f '/sdcard/tether.state' ]
then
echo 'Setting up NAT'
touch /sdcard/tether.state
ndc nat enable eth0 tun0 99
ndc ipfwd add eth0 tun0
ip6tables -t nat -N natctrl_nat_POSTROUTING
ip6tables -t nat -A POSTROUTING -j natctrl_nat_POSTROUTING
ip6tables -t nat -A natctrl_nat_POSTROUTING -o tun0 -j MASQUERADE
ip6tables -t filter -A natctrl_FORWARD -i tun0 -o eth0 -m state --state RELATED,ESTABLISHED -g natctrl_tether_counters
ip6tables -t filter -A natctrl_FORWARD -i eth0 -o tun0 -m state --state INVALID -j DROP
ip6tables -t filter -A natctrl_FORWARD -i eth0 -o tun0 -g natctrl_tether_counters
ip6tables -t filter -A natctrl_FORWARD -j DROP
fi
else
echo 'Skipping operation, USB not connected'
fi

eth0 is the Ethernet adapter and tun0 is the VPN interface. I also use a very similar script to do the same thing with RNDIS, you can setup all kinds of interesting tethering setups with these commands. If you want to run DHCP on the phone for use with a switch or cross-over cable or whatever, this command should work as root:

dnsmasq --keep-in-foreground --no-resolv --no-poll --dhcp-authoritative --dhcp-range=192.168.42.10,192.168.42.99,1h --dhcp-option=6,8.8.8.8,8.8.4.4 --dhcp-option-force=43,ANDROID_METERED --dhcp-leasefile=/sdcard/dnsmasq.leases --pid-file=/sdcard/dnsmasq.pid --listen-mark 0xf0063

Since this is a powered tethering setup, you probably want to use something to control charging:

https://play.google.com/store/apps/details?id=com.slash.batterychargelimit&hl=en&gl=US

On the router, set it's IP to 192.168.42.1, gateway to 192.168.42.129, DNS servers, and DHCP range to 192.168.42.10-192.168.42.99. Disable IPv6 support if it has it. Don't plug anything into the WAN (yellow) port, the phone connects to LAN.

Moto E5 Play kernel with IPv6 NAT support

https://drive.google.com/file/d/15IDtuuOn60bgw5FHVnoacexe2fjzuHcg/view?usp=sharing

ipconfig.txt, radvd, radvd.conf, tether.sh

https://drive.google.com/file/d/18YL4rYyF9tFu34WI_wzBLNtiUDp9U7_a/view?usp=sharing

I wrote an app to manage this, but it still needs a bit of work to handle custom configurations.