Hi Bartek,

I’m also using an Android phone for USB tethering over 5G. 90% of the time it 
works 100% of the time ;) After the iniital setup and troubleshooting I came up 
with the router configuration detailed below.

Background
Temporary setup at an airbnb with poor wifi (heavy interference, variable 
throughput). 5G provides better peak performance but still fluctuates with 
load. Router wifi client is limited to 2.4 GHz due to older hardware.

I setup hotplugd attach to remove ral from egress, remov autoconf and pull the 
ral default route from the table. I leave ral up and associated with the AP 
(when on 5G) that way when I transiton back to ral I just need to add it to the 
egress group, add autoconf flag and re-insert the default route.

I’ve also dropped unbound and now use public DNS. resolvd is disabled, and 
there’s no dhcpd on the LAN—everything is statically configured, for now.

Objective
OpenBSD i386/7.8 ALIX router that prefers wifi but automatically switches to 
urndis when USB is connected, with minimal packet loss, and falls back to wifi 
on disconnect. Router with ral (wifi) and vr (LAN). pf for NAT/filtering. 
hotplugd detects urndis and triggers reconfiguration of interfaces and routes.

Outstanding Issues
For some reason my setup doesn’t always switch cleanly to the urndis interface 
on initial connect. Not sure if the issue is the phone, urndis, or my setup. 
For example; the first time I connect USB initial connect/disconnect seems to 
get stuck transitioning to 5G but subsequent cycles are flawless. If I leave it 
on wifi for a day and come back to connect USB I have to plug/unplug to get it 
to transition cleanly.

The other issue is sometimes the 5G connection gets to congested and packets 
stop flowing throught the phone and I have to connect/disconnect again. Might 
have to setup ifstated to check for this condition and reinitialize the 
interface.

Open to suggestions on making this setup more robust or possibly even setting 
it up for active/active, dependent on which WAN has better throughput in the 
moment.


router:/home/admin $ cat /etc/hostname.vr0
inet 172.16.100.1 255.255.255.0
up
### EOF

router:/home/admin $ cat /etc/hostname.ral0
nwid "..." wpakey ...
inet autoconf
up
### EOF

router:/home/admin $ doas cat /etc/pf.conf:
# Marcros
lan_if = "vr0"
wlan_if = "ral0"

# Options
set block-policy drop
set skip on lo0

# Match rules
match in all scrub (no-df random-id max-mss 1440)
match out on egress to any nat-to (egress)

# Block rules
antispoof quick for egress
block all

# Filtering rules
pass quick on egress inet proto { tcp, udp } to any port { bootps, bootpc }
pass in quick on $lan_if inet proto tcp from $lan_if:network to ($lan_if) port 
ssh
pass on $lan_if from $lan_if:network to any label "clear"
pass out on egress to any label "clear"
### EOF

router:/home/admin $ doas cat /etc/hotplug/attach
#!/bin/sh

DEVCLASS=$1
DEVNAME=$2

case $DEVCLASS in
3)
        case $DEVNAME in
                urndis0)
                        logger "hotplugd: USB tethering device urndis0 attached"

                        logger "hotplugd: bringing up urndis0 interface"
                        ifconfig $DEVNAME autoconf && sleep 3

                        logger "hotplugd: deleting default route via ral0"
                        ral0defaultroute=$(grep "next-server" 
/var/db/dhcpleased/ral0 | awk '{print $2}')
                        route delete default $ral0defaultroute -ifp ral0
                        ifconfig ral0 -autoconf -group egress

                        logger "hotplugd: flushing states"
                        pfctl -k label -k clear

                        logger "hotplugd: end of attach script"
        ;;
        esac
esac
### EOF

router:/home/admin $ doas cat /etc/hotplug/detach
#!/bin/sh

DEVCLASS=$1
DEVNAME=$2

case $DEVCLASS in
3)
        case $DEVNAME in
                urndis0)
                        logger "hotplugd: USB tethering device urndis0 detached"

                        logger "hotplugd: checking to see if ral0 is active"
                        ifconfig ral0 | grep -q "status: active"
                        ral0_status=$?

                        if [[ $ral0_status -eq 0 ]]; then
                                logger "hotplugd: ral0 is active, adding 
default route"
                                ral0defaultroute=$(grep "next-server" 
/var/db/dhcpleased/ral0 | awk '{print $2}')
                                route add default $ral0defaultroute -ifp ral0
                                ifconfig ral0 autoconf group egress

                                logger "hotplugd: flushing states"
                                pfctl -k label -k clear

                        elif [[ $ral0_status -eq 1 ]]; then
                                logger "hotplugd: ral0 is not active, running 
netstart script"
                                sh /etc/netstart ral0

                        else
                                logger "hotplugd: can't determine status of 
ral0"
                        fi

                        logger "hotplugd: end of detach script"
        ;;
        esac
esac
###EOF


### Router state on ral wireless...

router:/home/admin $ doas dhcpleased -v -d
state_transition[ral0] Down -> Rebooting, timo: 1
DHCPREQUEST on ral0
DHCPACK on ral0 from 22:6a:94:99:52:41/192.168.0.1 to 
00:14:85:d3:f2:8e/192.168.0.132
adding 192.168.0.132 to ral0 (lease from 192.168.0.1)
adding nameservers 192.168.0.1 (lease from 192.168.0.1 on ral0)
state_transition[ral0] Rebooting -> Bound, timo: 43200
configure_interface ral0


router:/home/admin $ doas ifconfig egress
ral0: flags=808843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,AUTOCONF4> mtu 1500
        lladdr 00:14:85:d3:f2:8e
        index 4 priority 4 llprio 3
        groups: wlan egress
        media: IEEE802.11 autoselect (OFDM36 mode 11g)
        status: active
        ieee80211: nwid "..." chan 1 bssid 20:6a:94:99:52:48 -109dBm wpakey 
wpaprotos wpa2 wpaakms psk wpaciphers ccmp wpagroupcipher ccmp
        inet 192.168.0.132 netmask 0xffffff00 broadcast 192.168.0.255


router:/home/admin $ doas route -n show -inet
Routing tables

Internet:
Destination        Gateway            Flags   Refs      Use   Mtu  Prio Iface
default            192.168.0.1        UGS        1      126     -    12 ral0
127.0.0.1          127.0.0.1          UHl        0      457 32768     1 lo0
172.16.100/24      172.16.100.1       UCn        1      346     -     4 vr0
172.16.100.1       00:0d:b9:0d:a8:1c  UHLl       0    18306     -     1 vr0
172.16.100.2       20:7b:d2:33:53:e7  UHLc       1  1934340     - L   3 vr0
172.16.100.255     172.16.100.1       UHb        0    78640     -     1 vr0
192.168.0/24       192.168.0.132      UCn        1        0     -     8 ral0
192.168.0.1        22:6a:94:99:52:41  UHLch      1        4     -     7 ral0
192.168.0.132      00:14:85:d3:f2:8e  UHLl       0        3     -     1 ral0
192.168.0.255      192.168.0.132      UHb        0        0     -     1 ral0


### Router state after connecting Android phone...

router:/home/admin $ doas dhcpleased -v -d (cont'd)
state_transition[urndis0] Down -> Rebooting, timo: 1
DHCPREQUEST on urndis0
DHCPACK on urndis0 from fe:1a:ce:27:08:df/10.41.194.246 to 
9a:c7:ab:49:28:aa/10.41.194.214
adding 10.41.194.214 to urndis0 (lease from 10.41.194.246)
adding nameservers 10.41.194.246 (lease from 10.41.194.246 on urndis0)
state_transition[urndis0] Rebooting -> Bound, timo: 1800
configure_interface urndis0
Removed autoconf flag from ral0
deleting nameservers 192.168.0.1 (lease from 192.168.0.1 on ral0)
deleting 192.168.0.132 from ral0 (lease from 192.168.0.1)
deconfigure_interface ral0


router:/home/admin $ doas ifconfig egress
urndis0: flags=808843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,AUTOCONF4> mtu 1500
        lladdr 9a:c7:ab:49:28:aa
        index 89 priority 0 llprio 3
        groups: egress
        inet 10.41.194.214 netmask 0xffffff00 broadcast 10.41.194.255


router:/home/admin $ doas ifconfig ral0
ral0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        lladdr 00:14:85:d3:f2:8e
        index 4 priority 4 llprio 3
        groups: wlan
        media: IEEE802.11 autoselect (OFDM36 mode 11g)
        status: active
        ieee80211: nwid "..." chan 1 bssid 20:6a:94:99:52:48 -107dBm wpakey 
wpaprotos wpa2 wpaakms psk wpaciphers ccmp wpagroupcipher ccmp


router:/home/admin $ doas route -n show -inet
Routing tables

Internet:
Destination        Gateway            Flags   Refs      Use   Mtu  Prio Iface
default            10.41.194.246      UGS        1      936     -     8 urndis0
10.41.194/24       10.41.194.214      UCn        1        0     -     4 urndis0
10.41.194.214      9a:c7:ab:49:28:aa  UHLl       0       11     -     1 urndis0
10.41.194.246      fe:1a:ce:27:08:df  UHLch      1       12     -     3 urndis0
10.41.194.255      10.41.194.214      UHb        0        0     -     1 urndis0
127.0.0.1          127.0.0.1          UHl        0      457 32768     1 lo0
172.16.100/24      172.16.100.1       UCn        1      346     -     4 vr0
172.16.100.1       00:0d:b9:0d:a8:1c  UHLl       0    18307     -     1 vr0
172.16.100.2       20:7b:d2:33:53:e7  UHLc       1  1935000     - L   3 vr0
172.16.100.255     172.16.100.1       UHb        0    78640     -     1 vr0


### LAN client traceroute before transition to 5G...
c:\>tracert 1.1.1.1

Tracing route to one.one.one.one [1.1.1.1]
over a maximum of 30 hops:

  1    <1 ms    <1 ms    <1 ms  yeg-router [172.16.100.1]
  2     3 ms     5 ms     3 ms  192.168.0.1
  3    17 ms    18 ms    16 ms  68.148.160.1
  4    16 ms    15 ms    18 ms  rc2ar-be131-1.ed.shawcable.net [64.59.184.137]
...
15    31 ms    32 ms    29 ms  one.one.one.one [1.1.1.1]

Trace complete.


### LAN client ping response during transition to 5G...
c:\>ping -t 1.1.1.1

Pinging 1.1.1.1 with 32 bytes of data:
Reply from 1.1.1.1: bytes=32 time=29ms TTL=58
Reply from 1.1.1.1: bytes=32 time=30ms TTL=58
Reply from 1.1.1.1: bytes=32 time=33ms TTL=58
Reply from 1.1.1.1: bytes=32 time=38ms TTL=58
Reply from 1.1.1.1: bytes=32 time=32ms TTL=58
Reply from 1.1.1.1: bytes=32 time=35ms TTL=58 <--- connect USB
Request timed out.
Reply from 1.1.1.1: bytes=32 time=58ms TTL=47
Reply from 1.1.1.1: bytes=32 time=61ms TTL=47
Reply from 1.1.1.1: bytes=32 time=56ms TTL=47
Reply from 1.1.1.1: bytes=32 time=43ms TTL=47
Reply from 1.1.1.1: bytes=32 time=44ms TTL=47
Reply from 1.1.1.1: bytes=32 time=66ms TTL=47
Reply from 1.1.1.1: bytes=32 time=61ms TTL=47
Reply from 1.1.1.1: bytes=32 time=48ms TTL=47
Reply from 1.1.1.1: bytes=32 time=69ms TTL=47
Reply from 1.1.1.1: bytes=32 time=53ms TTL=47

Ping statistics for 1.1.1.1:
    Packets: Sent = 17, Received = 16, Lost = 1 (5% loss),
Approximate round trip times in milli-seconds:
    Minimum = 29ms, Maximum = 69ms, Average = 47ms
Control-C
^C


### Router ping response during transition to 5G...
router:/home/admin $ ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1): 56 data bytes
64 bytes from 1.1.1.1: icmp_seq=0 ttl=59 time=31.484 ms
64 bytes from 1.1.1.1: icmp_seq=1 ttl=59 time=32.699 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=59 time=32.148 ms
64 bytes from 1.1.1.1: icmp_seq=3 ttl=59 time=30.861 ms
64 bytes from 1.1.1.1: icmp_seq=4 ttl=59 time=34.582 ms <--- connect USB
64 bytes from 1.1.1.1: icmp_seq=8 ttl=48 time=59.442 ms
64 bytes from 1.1.1.1: icmp_seq=9 ttl=48 time=51.786 ms
64 bytes from 1.1.1.1: icmp_seq=10 ttl=48 time=46.138 ms
64 bytes from 1.1.1.1: icmp_seq=11 ttl=48 time=38.190 ms
64 bytes from 1.1.1.1: icmp_seq=12 ttl=48 time=48.407 ms
64 bytes from 1.1.1.1: icmp_seq=13 ttl=48 time=42.599 ms
^C


### LAN client traceroute after transition to 5G...
c:\>tracert 1.1.1.1

Tracing route to one.one.one.one [1.1.1.1]
over a maximum of 30 hops:

  1    <1 ms    <1 ms    <1 ms  yeg-router [172.16.100.1]
  2     2 ms     2 ms     2 ms  10.41.194.246
  3     6 ms     3 ms     3 ms  192.0.0.1
  4     *        *        *     Request timed out.
...
18    83 ms    42 ms    61 ms  one.one.one.one [1.1.1.1]

Trace complete.


### LAN client ping behaviour during transition back to ral wireless...
c:\>ping -t 1.1.1.1

Pinging 1.1.1.1 with 32 bytes of data:
Reply from 1.1.1.1: bytes=32 time=72ms TTL=47
Reply from 1.1.1.1: bytes=32 time=48ms TTL=47
Reply from 1.1.1.1: bytes=32 time=60ms TTL=47
Reply from 1.1.1.1: bytes=32 time=74ms TTL=47
Reply from 1.1.1.1: bytes=32 time=60ms TTL=47 <--- disconnect USB
Reply from 1.1.1.1: bytes=32 time=33ms TTL=58
Reply from 1.1.1.1: bytes=32 time=31ms TTL=58
Reply from 1.1.1.1: bytes=32 time=32ms TTL=58
Reply from 1.1.1.1: bytes=32 time=33ms TTL=58
Reply from 1.1.1.1: bytes=32 time=32ms TTL=58
Reply from 1.1.1.1: bytes=32 time=33ms TTL=58

Ping statistics for 1.1.1.1:
    Packets: Sent = 11, Received = 11, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 31ms, Maximum = 74ms, Average = 46ms
Control-C
^C


### Router ping behaviour during transition back to ral wireless...
router:/home/admin $ ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1): 56 data bytes
64 bytes from 1.1.1.1: icmp_seq=0 ttl=48 time=47.390 ms
64 bytes from 1.1.1.1: icmp_seq=1 ttl=48 time=72.350 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=48 time=61.727 ms
64 bytes from 1.1.1.1: icmp_seq=3 ttl=48 time=52.997 ms
64 bytes from 1.1.1.1: icmp_seq=4 ttl=48 time=69.023 ms <--- disconnect USB
ping: sendmsg: Can't assign requested address
ping: wrote 1.1.1.1 64 chars, ret=-1
64 bytes from 1.1.1.1: icmp_seq=6 ttl=59 time=36.700 ms
64 bytes from 1.1.1.1: icmp_seq=7 ttl=59 time=64.899 ms
64 bytes from 1.1.1.1: icmp_seq=8 ttl=59 time=38.605 ms
64 bytes from 1.1.1.1: icmp_seq=10 ttl=59 time=32.515 ms
^C


### LAN client traceroute after transition back to ral wireless...
c:\>tracert 1.1.1.1

Tracing route to one.one.one.one [1.1.1.1]
over a maximum of 30 hops:

  1    <1 ms    <1 ms    <1 ms  yeg-router [172.16.100.1]
  2     7 ms     2 ms     3 ms  192.168.0.1
  3    16 ms    14 ms    16 ms  68.148.160.1
  4    37 ms    15 ms    15 ms  rc2ar-be131-1.ed.shawcable.net [64.59.184.137]
...
15    29 ms    32 ms    35 ms  one.one.one.one [1.1.1.1]

Trace complete.


Cheers,
Byron


On Tue, Mar 17, 2026, at 16:07, Bartek Dygas wrote:
> On 3/17/26 12:21 AM, Zé Loff wrote:
>> Does your mobile ISP support tethering/connection sharing?  I've had
>> issues with a provider that only allows for the phone itself to access
>> the internet, and blocks shared connections.
> Yes, USB Tethering with this phone works correctly on a different 
> computer with ArchLinux.
>
> Attachments:
> * OpenPGP_0x5AEF30C3C0EAEC93.asc
> * OpenPGP_signature.asc

On Tue, Mar 17, 2026, at 16:07, Bartek Dygas wrote:
> On 3/17/26 12:21 AM, Zé Loff wrote:
>> Does your mobile ISP support tethering/connection sharing?  I've had
>> issues with a provider that only allows for the phone itself to access
>> the internet, and blocks shared connections.
> Yes, USB Tethering with this phone works correctly on a different 
> computer with ArchLinux.
>
> Attachments:
> * OpenPGP_0x5AEF30C3C0EAEC93.asc
> * OpenPGP_signature.asc

-- 
Byron Klippert      
  [email protected]

Reply via email to