Raspberry Pi 5 + EG25-G QMI Setup - LTE Works But Tailscale VPN Won't Bind to LTE Interface

Hardware:

  • Raspberry Pi 5

  • Sixfab HAT with Quectel EG25-G modem

  • Kore Super SIM

  • Debian GNU/Linux 13 (trixie), Kernel 6.12.47+rpt-rpi-2712

Modem Details:

  • Model: Quectel EG25-G

  • IMEI: 868998081647378

  • Firmware: EG25GGBR07A08M2G_30.203.30.203

  • USB Mode: QMI (usbnet mode 0)

  • QMI Device: /dev/cdc-wdm0 ✓

Network Details:

  • Carrier: AT&T (310410) via Kore/Twilio

  • Connection: LTE Band 2, Roaming

  • Signal: CSQ 21 (good)

  • APN: super


Current Status:

I’ve successfully followed the official Sixfab QMI guide (https://docs.sixfab.com/page/setting-up-a-data-connection-over-qmi-interface-using-libqmi) and have QMI working with auto-connect on boot via systemd service.

What Works: :white_check_mark: Modem detection and QMI mode configuration :white_check_mark: Automatic QMI connection on boot (systemd service) :white_check_mark: LTE internet connectivity (ping, curl work over wwan0) :white_check_mark: LTE interface receives proper IP (100.85.172.123/29) :white_check_mark: Default route via LTE gateway (100.85.172.124) with metric 50 :white_check_mark: DNS resolution works

What Doesn’t Work: :cross_mark: Tailscale VPN binds to WiFi interface instead of LTE :cross_mark: LTE-only operation becomes unstable after some time :cross_mark: Remote access via Tailscale fails when WiFi is disabled


Setup Details:

QMI Connection (systemd service /etc/systemd/system/qmi-connect.service):

[Unit]
Description=QMI LTE Connection
Before=tailscaled.service
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/qmi-connect.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Connection Script (/usr/local/bin/qmi-connect.sh)

#!/bin/bash
sleep 10

Configure wwan0 for QMI

ip link set wwan0 down 2>/dev/null || true
echo ‘Y’ > /sys/class/net/wwan0/qmi/raw_ip
ip link set wwan0 up

Start network

qmicli -p -d /dev/cdc-wdm0 --device-open-net=‘net-raw-ip|net-no-qos-header’
–wds-start-network=“apn=‘super’,ip-type=4” --client-no-release-cid

sleep 5

Get IP settings

SETTINGS=$(qmicli -d /dev/cdc-wdm0 --wds-get-current-settings)
IP=$(echo “$SETTINGS” | grep “IPv4 address:” | awk ‘{print $3}’)
GW=$(echo “$SETTINGS” | grep “gateway address:” | awk ‘{print $4}’)

if [ -n “$IP” ] && [ -n “$GW” ]; then
ip addr add ${IP}/29 dev wwan0 2>/dev/null || true
ip link set wwan0 up
sleep 2
ip route add default via ${GW} dev wwan0 metric 50 2>/dev/null || true
echo “nameserver 8.8.8.8” > /etc/resolv.conf
logger “QMI connected: IP=$IP GW=$GW”
fi


**Current Routing:**

default via 100.85.172.124 dev wwan0 metric 50
default via 192.168.1.254 dev wlan0 proto dhcp src 192.168.1.250 metric 600
100.85.172.120/29 dev wwan0 proto kernel scope link src 100.85.172.123
192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.250 metric 600


**Tailscale Issue:**

$ sudo tailscale netcheck
portmap: monitor: gateway and self IP changed: gw=192.168.1.254 self=192.168.1.250


Despite LTE having lower metric (50 vs 600), Tailscale consistently binds to WiFi gateway (192.168.1.254) instead of LTE gateway (100.85.172.124).

---

**Troubleshooting Steps Attempted:**

1. ✓ Disabled ModemManager to avoid conflicts
2. ✓ Created systemd service to start QMI before Tailscale
3. ✓ Verified QMI connection with `qmicli --wds-get-packet-service-status` (shows "connected")
4. ✓ Tested LTE connectivity with `curl --interface wwan0 http://www.google.com` (works)
5. ✓ Restarted Tailscale after LTE established
6. ✓ Tried `tailscale up --accept-routes --netfilter-mode=off`
7. ✓ Added policy routing rules with `ip rule` and `ip route`
8. ❌ Tailscale still binds to WiFi regardless

**LTE Stability Issue:**
When running for extended periods, LTE connection shows as "connected" via qmicli but stops passing packets (100% packet loss). Requires service restart or full reboot.

---

**Use Case:**
LTE relay requiring reliable remote access via Tailscale VPN over cellular connection without WiFi dependency.

---

**Questions:**

1. **Is there a known method to force Tailscale (or other VPNs) to bind to wwan0 instead of WiFi when both are present?**

2. **Why does the LTE connection become unstable over time despite qmicli showing "connected"?** Is this a known issue with sustained QMI connections?

3. **Are there recommended systemd ordering or networking configurations for LTE-only VPN scenarios?**

4. **Would switching to ECM mode provide more stable operation for this use case?**

Any guidance would be greatly appreciated! Full diagnostic logs available if needed.

---

**Diagnostic Summary:**

**AT Commands (all returning OK):**
- Registration: `+CREG: 0,5` (registered, roaming)
- Signal: `+CSQ: 21,99`
- Network: `+QNWINFO: "FDD LTE","310410","LTE BAND 2",1025`
- SIM: `+CPIN: READY`
- Attached: `+CGATT: 1`
- APN: `+CGDCONT: 1,"IP","super","0.0.0.0",0,0,0,0`

**System:**

$ lsusb | grep Quectel
Bus 003 Device 003: ID 2c7c:0125 Quectel Wireless Solutions Co., Ltd. EC25 LTE modem

$ ls /dev/ttyUSB*
/dev/ttyUSB0 /dev/ttyUSB1 /dev/ttyUSB2 /dev/ttyUSB3

$ ls /dev/cdc-wdm*
/dev/cdc-wdm0

Hello @telemetryflightservi

Tailscale does not reliably honor Linux route metrics when multiple default routes exist. As long as a valid Wi-Fi default route is present, it may bind to Wi-Fi even if LTE has a lower metric. The most reliable fix is to remove (or heavily de-prioritize) the Wi-Fi default route after LTE is up, then restart Tailscale so it detects LTE (wwan0) as the primary interface.

Add this at the end of your qmi-connect.sh, after adding the LTE default route:

# Remove competing Wi-Fi default route
ip route del default via 192.168.1.254 dev wlan0 2>/dev/null || true

Then restart Tailscale:

sudo systemctl restart tailscaled

(Optional: if you want Wi-Fi only as a fallback, set a very high metric instead of deleting the route.)

After this, tailscale netcheck should report the LTE gateway, and Tailscale will bind to wwan0 reliably.