Aoik

Soft router with Internet via USB tethering

Buy a mini PC

I use a Nano-ITX (12 × 12 cm) board.

Install Linux

Install Linux on the mini PC. I use Debian 11.

Connect mobile phone

Internet access of the mini PC is provided via a mobile phone's USB tethering.

Connect the mobile phone to the mini PC via a USB cable.

Select USB network sharing mode or something alike on the mobile phone.

Run:

ip addr

A network adapter named usb0 or something alike should appear.

Run:

dhclient -v usb0

The network adapter should get network settings set up via DHCP.
The DHCP service is provided by the mobile phone's virtual router.

Now that we have got Internet access on the mini PC, next we need configure the mini PC to become a soft router.

Bridge Ethernet ports

My mini PC has two Ethernet ports. Their network adapters are named enp3s0 and enp4s0, respectively. To work as a soft router, it is preferred to bridge the two network adapters as a single network adapter, so that devices connected to the two ports are within the same subnet.

Run:

cat <<'ZZZ' > /etc/network/interfaces
auto lo
iface lo inet loopback

iface enp3s0 inet manual

iface enp4s0 inet manual

auto br0
iface br0 inet static
bridge_ports enp3s0 enp3s4
address 10.0.0.254
netmask 255.255.255.0

iface usb0 inet manual
ZZZ

systemctl restart networking
# or
reboot

10.0.0.254 is the bridge adapter's IP address.

Make sure network adapter br0 is up:

ip addr

Enable OS routing

Run:

cp -av /etc/sysctl.conf /etc/sysctl.old.conf

cat <<'ZZZ' > /etc/sysctl.conf
net.ipv4.tcp_syncookies = 1
net.ipv4.ip_forward = 1
net.ipv4.conf.all.accept_redirects = 1
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.send_redirects = 1
net.ipv4.conf.all.accept_source_route = 1
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
ZZZ

sysctl -p

Set up iptables

Install iptables-persistent:

apt-get install -y iptables-persistent

Configure iptables:

cat <<'ZZZ' >> /etc/iptables/rules.v4
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A FORWARD -j ACCEPT
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:FORWARD - [0:0]
-A POSTROUTING -s 10.0.0.0/24 -o usb0 -m comment --comment "NAT for intranet" -j MASQUERADE
COMMIT
ZZZ

iptables-restore /etc/iptables/rules.v4

For the intranet's IP packets going out to Internet, postrouting masquerade, i.e. NAT, is required because their source IP address is intranet address, which is not routable on Internet during return trip.

Set up dnsmasq

Install dnsmasq:

apt -y install dnsmasq

Configure dnsmasq:

cat <<'ZZZ' > /etc/dnsmasq.conf
# Never forward plain names.
domain-needed

# Never forward addresses in the non-routed address spaces.
bogus-priv

# Query with each server strictly in the order in resolv.conf.
strict-order

# Add domain name automatically.
expand-hosts

# Is authoritative DHCP server.
dhcp-authoritative

# Interface.
interface=br0

# Local domain.
domain=home.local

# Dynamic IP assignment.
dhcp-range=10.0.0.240,10.0.0.249,255.255.255.0,1h

# Static IP assignment.
dhcp-host=00:00:00:00:00:01,host1,10.0.0.1,infinite
ZZZ

Start dnsmasq:

systemctl restart dnsmasq

Configure udev rule

One drawback of using a mobile phone as the Internet router is it may be plugged off often, when you need carry it to toilet for example. Having to re-run dhclient each time is inconvenient. What makes it even more inconvenient is that I've got a bunch of services that need be restarted each time the soft router's Internet resumes.

The udev event system comes to the rescue. We can run a script when the mobile phone's USB cable connects back. The key here is finding the right udev event.

List USB devices:

lsusb

Result:

...
Bus 001 Device 005: ID 22b8:2e24 Motorola PCS XT2175-2
...

The 001:005 is the "bus_num:device_num" that may vary with the USB port to which the mobile phone is connected.

The 22b8:2e24 is the "vendor_id:product_id" that is a phone-specific fixed value.

List the udev properties of the mobile phone:

udevadm info --query=property /dev/bus/usb/001/005

Result:

DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-2
DEVNAME=/dev/bus/usb/001/005
DEVTYPE=usb_device
DRIVER=usb
PRODUCT=22b8/2e24/504
TYPE=0/0/0
BUSNUM=001
DEVNUM=005
MAJOR=189
MINOR=4
SUBSYSTEM=usb
USEC_INITIALIZED=115177231
ID_VENDOR=motorola
ID_VENDOR_ENC=motorola
ID_VENDOR_ID=22b8
ID_MODEL=XT2175-2
ID_MODEL_ENC=XT2175-2
ID_MODEL_ID=2e24
ID_REVISION=0504
ID_SERIAL=motorola_XT2175-2_ZY22F62M75
ID_SERIAL_SHORT=ZY22F62M75
ID_BUS=usb
ID_USB_INTERFACES=:ef0401:0a0000:
ID_VENDOR_FROM_DATABASE=Motorola PCS
ID_PATH=pci-0000:00:14.0-usb-0:2
ID_PATH_TAG=pci-0000_00_14_0-usb-0_2
ID_FOR_SEAT=usb-pci-0000_00_14_0-usb-0_2
TAGS=:seat:
CURRENT_TAGS=:seat:

Create a udev rule:

cat <'ZZZ' > /etc/udev/rules.d/10-local.rules
ACTION=="bind", ATTR{manufacturer}=="motorola", ATTR{product}=="XT2175-2", ATTR{idProduct}=="2e24", ATTR{idVendor}=="22b8", RUN{program}+="/usr/bin/bash /opt/mobile_phone_on_connect_phase1.sh"
ZZZ

Create udev rule phase1 script:

cat <<'ZZZ' > /opt/mobile_phone_on_connect_phase1.sh
#!/usr/bin/env bash

echo /opt/mobile_phone_on_connect_phase2.sh | /usr/bin/at now
ZZZ

Create udev rule phase2 script:

cat <<'ZZZ' > /opt/mobile_phone_on_connect_phase2.sh
#!/usr/bin/env bash

/usr/bin/killall dhclient

/usr/bin/sleep 1

/usr/sbin/dhclient -v usb0 > /opt/dhclient.log 2>&1

/usr/bin/sleep 1

# Restart other services.
# ...

The reason to split into two udev rule scripts is that long running script, even if only 1 or 2 seconds, will get killed by the udev event system.

Now each time the mobile phone reconnects to the soft router, the soft router's Internet resumes automatically.

Comments:

Reply to: