NAND 128MB (GigaDevice SPI NAND) + NOR 16MB (Winbond W25Q128)
defined
tested
ethernetwifiusb
GL.iNet
AR300M / AR300M-Ext (NOR boot). NOT recommended for general use — NAND is 128MB vs NOR's 16MB. NOR is useful as automatic failsafe recovery partition. NOR boot via switch RIGHT (bootm 0x9f050000) or bootcount method (fw_setenv bootcount 3). Switch-based NOR boot may not work on all U-Boot versions. glinet-gl-ar300m-nor
QCA9533 v2 (MIPS 24Kc) @ 650MHz
128MB DDR2
NAND 128MB (GigaDevice SPI NAND) + NOR 16MB (Winbond W25Q128)
AR300M / AR300M-Ext (NOR boot). NOT recommended for general use — NAND is 128MB vs NOR's 16MB. NOR is useful as automatic failsafe recovery partition. NOR boot via switch RIGHT (bootm 0x9f050000) or bootcount method (fw_setenv bootcount 3). Switch-based NOR boot may not work on all U-Boot versions. glinet-gl-ar300m-nor
WireGuard VPN client — route traffic through a VPN tunnel
tested D-Link COVR-X1860 A1
none
wireguard-tools, luci-proto-wireguard
wireguard-server
WireGuard VPN server — remote access to home network
tested ops characterization + transport parity
none
wireguard-tools, luci-proto-wireguard, qrencode
# --- AdGuard Home ---
uci set adguardhome.adguardhome=adguardhome
uci set adguardhome.adguardhome.enabled='1'
uci set adguardhome.adguardhome.http_address='0.0.0.0:3000'
uci set adguardhome.adguardhome.dns_port='5353'
uci commit adguardhome
/etc/init.d/adguardhome enable
/etc/init.d/adguardhome start
uci set dhcp.@dnsmasq[0].noresolv='1'
uci add_list dhcp.@dnsmasq[0].server='127.0.0.1#5353'
uci commit dhcp
/etc/init.d/dnsmasq restart
echo "AdGuard Home configured: DNS on port 5353, web UI at 0.0.0.0:3000"
# --- Auto-SQM ---
touch /etc/config/auto_sqm
uci set auto_sqm.config=auto_sqm
uci set auto_sqm.config.mode='static'
uci set auto_sqm.config.interface='wan'
uci set auto_sqm.config.device='eth0'
uci set auto_sqm.config.target_percent='90'
uci set auto_sqm.config.qdisc='cake'
uci set auto_sqm.config.script='piece_of_cake.qos'
uci set auto_sqm.config.measurement_mode='wget'
uci set auto_sqm.config.iperf3_host=''
uci set auto_sqm.config.iperf3_port='5201'
uci set auto_sqm.config.test_url='http://speedtest.tele2.net/10MB.zip'
uci set auto_sqm.config.download_kbps='0'
uci set auto_sqm.config.upload_kbps='0'
uci set auto_sqm.config.upload_fallback_kbps='5000'
uci set auto_sqm.config.hysteresis_percent='10'
uci set auto_sqm.config.dynamic_interval_hours='4'
uci commit auto_sqm
cat <<'AUTO_SQM_EOF' > /usr/sbin/auto-sqm
#!/bin/sh
# auto-sqm — measure WAN link speed and configure SQM
MODE=$(uci -q get auto_sqm.config.mode || echo "static")
INTERFACE=$(uci -q get auto_sqm.config.interface || echo "wan")
DEVICE=$(uci -q get auto_sqm.config.device || echo "eth0")
TARGET_PCT=$(uci -q get auto_sqm.config.target_percent || echo "90")
QDISC=$(uci -q get auto_sqm.config.qdisc || echo "cake")
QOS_SCRIPT=$(uci -q get auto_sqm.config.script || echo "piece_of_cake.qos")
MEAS_MODE=$(uci -q get auto_sqm.config.measurement_mode || echo "wget")
IPERF3_HOST=$(uci -q get auto_sqm.config.iperf3_host || echo "")
IPERF3_PORT=$(uci -q get auto_sqm.config.iperf3_port || echo "5201")
TEST_URL=$(uci -q get auto_sqm.config.test_url || echo "")
UPLOAD_FALLBACK=$(uci -q get auto_sqm.config.upload_fallback_kbps || echo "5000")
HYSTERESIS=$(uci -q get auto_sqm.config.hysteresis_percent || echo "10")
DL_SPEED=0
UL_SPEED=0
measure_wget() {
[ -z "$DEVICE" ] && return 1
[ -z "$TEST_URL" ] && return 1
bytes_before=$(cat /sys/class/net/"$DEVICE"/statistics/rx_bytes 2>/dev/null) || return 1
t1=$(date +%s)
wget -O /dev/null -T 30 "$TEST_URL" 2>/dev/null || return 1
t2=$(date +%s)
bytes_after=$(cat /sys/class/net/"$DEVICE"/statistics/rx_bytes 2>/dev/null) || return 1
elapsed=$((t2 - t1))
[ "$elapsed" -eq 0 ] && elapsed=1
speed_bps=$(( (bytes_after - bytes_before) * 8 / elapsed ))
DL_SPEED=$((speed_bps / 1000))
DL_SPEED=$((DL_SPEED * TARGET_PCT / 100))
}
measure_iperf3() {
[ -z "$IPERF3_HOST" ] && return 1
command -v iperf3 >/dev/null 2>&1 || return 1
json_out=$(iperf3 -c "$IPERF3_HOST" -p "$IPERF3_PORT" -t 5 -J 2>/dev/null) || return 1
speed_bps=$(echo "$json_out" | jsonfilter -e "@.end.sum_received.bits_per_second" 2>/dev/null) || return 1
speed_bps=$(echo "$speed_bps" | cut -d. -f1)
DL_SPEED=$((speed_bps / 1000))
DL_SPEED=$((DL_SPEED * TARGET_PCT / 100))
}
apply_sqm() {
dl=$1
ul=$2
[ "$dl" -eq 0 ] && return 1
cur_dl=$(uci -q get sqm."$INTERFACE".download || echo "0")
cur_ul=$(uci -q get sqm."$INTERFACE".upload || echo "0")
if [ "$cur_dl" -gt 0 ] && [ "$cur_ul" -gt 0 ]; then
lo=$((100 - HYSTERESIS))
hi=$((100 + HYSTERESIS))
pct_dl=$((cur_dl * 100 / dl))
pct_ul=$((cur_ul * 100 / ul))
if [ "$pct_dl" -ge "$lo" ] && [ "$pct_dl" -le "$hi" ] && [ "$pct_ul" -ge "$lo" ] && [ "$pct_ul" -le "$hi" ]; then
echo "auto-sqm: change within hysteresis, skipping"
return 0
fi
fi
touch /etc/config/sqm
uci set sqm.$INTERFACE=queue
uci set sqm.$INTERFACE.interface="$INTERFACE"
uci set sqm.$INTERFACE.enabled='1'
uci set sqm.$INTERFACE.script="$QOS_SCRIPT"
uci set sqm.$INTERFACE.qdisc="$QDISC"
uci set sqm.$INTERFACE.linklayer='none'
uci set sqm.$INTERFACE.overhead='0'
uci set sqm.$INTERFACE.linklayer_adaptation_mechanism='default'
uci set sqm.$INTERFACE.debug_logging='0'
uci set sqm.$INTERFACE.verbosity='5'
uci set sqm.$INTERFACE.download="$dl"
uci set sqm.$INTERFACE.upload="$ul"
uci commit sqm
/etc/init.d/sqm enable
/etc/init.d/sqm restart 2>/dev/null || true
echo "auto-sqm: SQM applied ${dl}/${ul} kbit/s (${QDISC})"
}
STATIC_DL=$(uci -q get auto_sqm.config.download_kbps || echo "0")
STATIC_UL=$(uci -q get auto_sqm.config.upload_kbps || echo "0")
if [ "$MODE" = "static" ] && [ "$STATIC_DL" -gt 0 ]; then
DL_SPEED=$((STATIC_DL * TARGET_PCT / 100))
if [ "$STATIC_UL" -gt 0 ]; then
UL_SPEED=$((STATIC_UL * TARGET_PCT / 100))
else
UL_SPEED=$UPLOAD_FALLBACK
fi
else
if [ "$MEAS_MODE" = "iperf3" ] && [ -n "$IPERF3_HOST" ]; then
measure_iperf3 || measure_wget
else
measure_wget || measure_iperf3
fi
if [ "$DL_SPEED" -eq 0 ]; then
echo "auto-sqm: measurement failed, will retry on next trigger" >&2
exit 1
fi
if [ "$STATIC_UL" -gt 0 ]; then
UL_SPEED=$((STATIC_UL * TARGET_PCT / 100))
else
UL_SPEED=$UPLOAD_FALLBACK
fi
fi
apply_sqm "$DL_SPEED" "$UL_SPEED"
AUTO_SQM_EOF
chmod +x /usr/sbin/auto-sqm
mkdir -p /etc/hotplug.d/iface
cat <<'HOTPLUG_EOF' > /etc/hotplug.d/iface/10-sqm-autotune
#!/bin/sh
[ "$ACTION" = "ifup" ] && [ "$INTERFACE" = "wan" ] && /usr/sbin/auto-sqm &
HOTPLUG_EOF
chmod +x /etc/hotplug.d/iface/10-sqm-autotune
echo 'auto-sqm: will measure and configure on WAN ifup'
echo 'Auto-SQM configured'
# --- DNS-over-HTTPS (cloudflare) ---
uci -q delete https-dns-proxy >/dev/null 2>&1 || true
uci set https-dns-proxy.main=https_dns_proxy
uci set https-dns-proxy.main.bootstrap_dns='1.1.1.1,8.8.8.8'
uci set https-dns-proxy.main.listen_addr='127.0.0.1'
uci set https-dns-proxy.main.listen_port='5053'
uci set https-dns-proxy.main.resolver_url='https://cloudflare-dns.com/dns-query'
uci commit https-dns-proxy
/etc/init.d/https-dns-proxy enable
/etc/init.d/https-dns-proxy restart
# --- Point dnsmasq to DoH proxy on port 5053 ---
uci set dhcp.@dnsmasq[0].noresolv='1'
uci delete dhcp.@dnsmasq[0].server
uci add_list dhcp.@dnsmasq[0].server='127.0.0.1#5053'
uci commit dhcp
/etc/init.d/dnsmasq restart
echo "DoH configured: cloudflare on port 5053"
# --- Guest WiFi: 'Guest' ---
uci set network.guest=interface
uci set network.guest.proto='static'
uci set network.guest.ipaddr='192.168.4.1'
uci set network.guest.netmask='255.255.255.0'
uci commit network
uci set dhcp.guest=dhcp
uci set dhcp.guest.interface='guest'
uci set dhcp.guest.start='100'
uci set dhcp.guest.limit='50'
uci set dhcp.guest.leasetime='1h'
uci commit dhcp
uci set firewall.guest=zone
uci set firewall.guest.name='guest'
uci set firewall.guest.network='guest'
uci set firewall.guest.input='REJECT'
uci set firewall.guest.output='ACCEPT'
uci set firewall.guest.forward='REJECT'
uci set firewall.guest_fwd=forwarding
uci set firewall.guest_fwd.src='guest'
uci set firewall.guest_fwd.dest='wan'
uci set firewall.guest_dns=rule
uci set firewall.guest_dns.name='Allow-DNS-guest'
uci set firewall.guest_dns.src='guest'
uci set firewall.guest_dns.dest_port='53'
uci set firewall.guest_dns.proto='tcpudp'
uci set firewall.guest_dns.target='ACCEPT'
uci set firewall.guest_dhcp=rule
uci set firewall.guest_dhcp.name='Allow-DHCP-guest'
uci set firewall.guest_dhcp.src='guest'
uci set firewall.guest_dhcp.dest_port='67-68'
uci set firewall.guest_dhcp.proto='udp'
uci set firewall.guest_dhcp.target='ACCEPT'
uci commit firewall
while uci show wireless 2>/dev/null | grep -q "network='guest'"; do _s=$(uci show wireless 2>/dev/null | grep "network='guest'" | head -1 | cut -d. -f2 | cut -d= -f1); uci delete "wireless.$_s" 2>/dev/null; done; true
_radio=""; for _r in radio0 radio1 radio2 radio3; do _b=$(uci get wireless.${_r}.band 2>/dev/null); if [ "$_b" = "2g" ]; then _radio=$_r; break; fi; done; if [ -n "$_radio" ]; then uci add wireless wifi-iface; uci set wireless.@wifi-iface[-1].device=$_radio; uci set wireless.@wifi-iface[-1].mode=ap; uci set wireless.@wifi-iface[-1].ssid='Guest'; uci set wireless.@wifi-iface[-1].encryption=psk2; uci set wireless.@wifi-iface[-1].network=guest; uci set wireless.@wifi-iface[-1].isolate=1; fi
uci commit wireless
/etc/init.d/network restart
/etc/init.d/firewall restart
echo "Guest WiFi configured: SSID='Guest' network=guest isolated=1"
# --- mwan3 multi-WAN ---
uci -q delete mwan3 >/dev/null 2>&1 || true
uci set mwan3.wan=interface
uci set mwan3.wan.enabled='1'
list track_ip '1.0.0.1'
list track_ip '1.1.1.1'
list track_ip '8.8.8.8'
list track_ip '8.8.4.4'
uci set mwan3.wan.family='ipv4'
uci set mwan3.wan.reliability='1'
uci set mwan3.wan.count='1'
uci set mwan3.wan.timeout='2'
uci set mwan3.wan.interval='5'
uci set mwan3.wan.down='3'
uci set mwan3.wan.up='8'
uci set mwan3.usbwan=interface
uci set mwan3.usbwan.enabled='1'
list track_ip '1.0.0.1'
list track_ip '1.1.1.1'
list track_ip '8.8.8.8'
list track_ip '8.8.4.4'
uci set mwan3.usbwan.family='ipv4'
uci set mwan3.usbwan.reliability='1'
uci set mwan3.usbwan.count='1'
uci set mwan3.usbwan.timeout='2'
uci set mwan3.usbwan.interval='5'
uci set mwan3.usbwan.down='3'
uci set mwan3.usbwan.up='8'
uci set mwan3.wan_m1_w1=member
uci set mwan3.wan_m1_w1.interface='wan'
uci set mwan3.wan_m1_w1.metric='1'
uci set mwan3.wan_m1_w1.weight='1'
uci set mwan3.usbwan_m2_w1=member
uci set mwan3.usbwan_m2_w1.interface='usbwan'
uci set mwan3.usbwan_m2_w1.metric='2'
uci set mwan3.usbwan_m2_w1.weight='1'
uci set mwan3.wan_policy=policy
uci add_list mwan3.wan_policy.use_member='wan_m1_w1'
uci add_list mwan3.wan_policy.use_member='usbwan_m2_w1'
uci set mwan3.wan_policy.last_resort='default'
uci set mwan3.default_rule_v4=rule
uci set mwan3.default_rule_v4.dest_ip='0.0.0.0/0'
uci set mwan3.default_rule_v4.use_policy='wan_policy'
uci set mwan3.default_rule_v4.family='ipv4'
uci set mwan3.https_rule=rule
uci set mwan3.https_rule.dest_port='443'
uci set mwan3.https_rule.proto='tcp'
uci set mwan3.https_rule.sticky='1'
uci set mwan3.https_rule.use_policy='wan_policy'
uci commit mwan3
/etc/init.d/mwan3 restart
echo "mwan3 configured: wan (primary) + usbwan (failover)"
# --- OpenClash transparent proxy ---
mkdir -p /etc/openclash/config
uci set openclash.config.enable='1'
uci set openclash.config.config_path='/etc/openclash/config/config.yaml'
uci set openclash.config.proxy_type='ss'
uci set openclash.config.core_type='Meta'
uci set openclash.config.dashboard_type='Official'
uci set openclash.config.dns_mode='redir-host'
uci set openclash.config.operation_mode='redir-host'
uci commit openclash
/etc/init.d/openclash enable
echo "OpenClash configured: Meta core, ss proxy"
echo "Post-flash: import your subscription config via the LuCI web UI"
# --- SQM Smart Queue Management ---
for _s in $(uci -q show sqm 2>/dev/null | grep '=queue' | cut -d. -f2 | cut -d= -f1); do uci -q delete sqm.$_s; done; true
_sqm_dev=$(uci get network.wan.device 2>/dev/null); if [ -z "$_sqm_dev" ] || ! ip addr show "$_sqm_dev" 2>/dev/null | grep -q "inet "; then _sqm_dev=$(ip route show default 0.0.0.0/0 2>/dev/null | awk '{print $5}' | head -1); fi; if [ -z "$_sqm_dev" ]; then _sqm_dev=wan; fi
uci set sqm.wan=queue
uci set sqm.wan.interface="$_sqm_dev"
uci set sqm.wan.enabled='1'
uci set sqm.wan.script='piece_of_cake.qos'
uci set sqm.wan.qdisc='cake'
uci set sqm.wan.linklayer='none'
uci set sqm.wan.overhead='0'
uci set sqm.wan.download='10000'
uci set sqm.wan.upload='5000'
uci set sqm.wan.linklayer_adaptation_mechanism='default'
uci set sqm.wan.debug_logging='0'
uci set sqm.wan.verbosity='5'
uci commit sqm
/etc/init.d/sqm enable
/etc/init.d/sqm restart
echo "SQM configured: 10000/5000 kbit/s (cake) on $_sqm_dev"
# --- SSH hardening ---
uci set dropbear.@dropbear[0].PasswordAuth='off'
uci set dropbear.@dropbear[0].RootPasswordAuth='off'
uci set dropbear.@dropbear[0].Port='22'
uci set dropbear.@dropbear[0].IdleTimeout='300'
uci set dropbear.@dropbear[0].MaxAuthTries='3'
uci set dropbear.@dropbear[0].GatewayPorts='no'
uci commit dropbear
/etc/init.d/dropbear restart
echo "SSH hardened: password_auth=off idle=300s max_tries=3 port=22"
# --- USB tethering (auto-detect) ---
/usr/sbin/usbmuxd -v -U -f >/dev/null 2>&1 &
USB_DEV=""
for _ in $(seq 1 45); do
for dev in /sys/class/net/*; do
name=$(basename "$dev")
case "$name" in
lo|br-lan|eth0|wlan*) continue ;;
esac
driver=$(readlink "$dev/device/driver" 2>/dev/null || true)
if echo "$driver" | grep -qi "rndis\|cdc_ether\|usbnet\|ipheth"; then
USB_DEV="$name"
break 2
fi
iface_desc=""
[ -e "$dev/device/interface" ] && iface_desc=$(cat "$dev/device/interface" 2>/dev/null || true)
if echo "$iface_desc" | grep -qi "apple\|iphone"; then
USB_DEV="$name"
break 2
fi
done
sleep 1
done
if [ -z "$USB_DEV" ]; then
for cand in usb0 usb1; do
[ -e "/sys/class/net/$cand" ] && USB_DEV="$cand" && break
done
fi
if [ -n "$USB_DEV" ]; then
uci set network.usbwan=interface
uci set network.usbwan.proto='dhcp'
uci set network.usbwan.device="$USB_DEV"
uci set network.usbwan.metric='20'
for _z in $(uci show firewall 2>/dev/null | grep '=zone' | cut -d. -f2 | cut -d= -f1 || true); do [ "$(uci -q get firewall.$_z.name)" = 'wan' ] && uci del_list firewall.$_z.network='usbwan' 2>/dev/null; uci add_list firewall.$_z.network='usbwan'; break; done
uci commit network
uci commit firewall
ifup usbwan 2>/dev/null || true
echo "USB tethering enabled on $USB_DEV -> usbwan"
else
echo "USB tethering: no USB network device found, skipping" >&2
fi
mkdir -p /etc/hotplug.d/usb
cat > /etc/hotplug.d/usb/99-usb-tether-adb << 'HOTPLUG_EOF'
[ "$ACTION" = "bind" ] || exit 0
[ "$PRODUCT" ] || exit 0
(
HOME=/root
export HOME
command -v adb >/dev/null 2>&1 || exit 0
DELAY=1
for attempt in 1 2 3 4 5 6 7; do
sleep $DELAY
if ip addr show usb0 2>/dev/null | grep -q "inet "; then
exit 0
fi
STATE=$(adb get-state 2>/dev/null)
if [ "$STATE" = "device" ]; then
adb shell svc usb setFunctions rndis 2>/dev/null
sleep 3
if ip addr show usb0 2>/dev/null | grep -q "inet "; then
logger -t usb-tether "ADB enabled tethering (attempt $attempt)"
exit 0
fi
fi
DELAY=$((DELAY * 2))
done
logger -t usb-tether "ADB tethering gave up after $attempt attempts"
) &
HOTPLUG_EOF
# --- Android USB tethering (manual) ---
USB_DEV=""
for _ in $(seq 1 45); do
for dev in /sys/class/net/*; do
name=$(basename "$dev")
case "$name" in
lo|br-lan|eth0|wlan*) continue ;;
esac
driver=$(readlink "$dev/device/driver" 2>/dev/null || true)
if echo "$driver" | grep -qi "rndis\|cdc_ether\|usbnet"; then
USB_DEV="$name"
break 2
fi
done
sleep 1
done
if [ -z "$USB_DEV" ]; then
for cand in usb0 usb1; do
[ -e "/sys/class/net/$cand" ] && USB_DEV="$cand" && break
done
fi
if [ -n "$USB_DEV" ]; then
uci set network.usbwan=interface
uci set network.usbwan.proto='dhcp'
uci set network.usbwan.device="$USB_DEV"
uci set network.usbwan.metric='20'
for _z in $(uci show firewall 2>/dev/null | grep '=zone' | cut -d. -f2 | cut -d= -f1 || true); do [ "$(uci -q get firewall.$_z.name)" = 'wan' ] && uci del_list firewall.$_z.network='usbwan' 2>/dev/null; uci add_list firewall.$_z.network='usbwan'; break; done
uci commit network
uci commit firewall
ifup usbwan 2>/dev/null || true
echo "USB tethering enabled on $USB_DEV -> usbwan"
else
echo "USB tethering: no USB network device found, skipping" >&2
fi
# --- Android USB tethering (ADB auto-enable) ---
USB_DEV=""
for _ in $(seq 1 45); do
for dev in /sys/class/net/*; do
name=$(basename "$dev")
case "$name" in
lo|br-lan|eth0|wlan*) continue ;;
esac
driver=$(readlink "$dev/device/driver" 2>/dev/null || true)
if echo "$driver" | grep -qi "rndis\|cdc_ether\|usbnet"; then
USB_DEV="$name"
break 2
fi
done
sleep 1
done
if [ -z "$USB_DEV" ]; then
for cand in usb0 usb1; do
[ -e "/sys/class/net/$cand" ] && USB_DEV="$cand" && break
done
fi
if [ -n "$USB_DEV" ]; then
uci set network.usbwan=interface
uci set network.usbwan.proto='dhcp'
uci set network.usbwan.device="$USB_DEV"
uci set network.usbwan.metric='20'
for _z in $(uci show firewall 2>/dev/null | grep '=zone' | cut -d. -f2 | cut -d= -f1 || true); do [ "$(uci -q get firewall.$_z.name)" = 'wan' ] && uci del_list firewall.$_z.network='usbwan' 2>/dev/null; uci add_list firewall.$_z.network='usbwan'; break; done
uci commit network
uci commit firewall
ifup usbwan 2>/dev/null || true
echo "USB tethering enabled on $USB_DEV -> usbwan"
else
echo "USB tethering: no USB network device found, skipping" >&2
fi
mkdir -p /etc/hotplug.d/usb
cat > /etc/hotplug.d/usb/99-usb-tether-adb << 'HOTPLUG_EOF'
[ "$ACTION" = "bind" ] || exit 0
[ "$PRODUCT" ] || exit 0
(
HOME=/root
export HOME
command -v adb >/dev/null 2>&1 || exit 0
DELAY=1
for attempt in 1 2 3 4 5 6 7; do
sleep $DELAY
if ip addr show usb0 2>/dev/null | grep -q "inet "; then
exit 0
fi
STATE=$(adb get-state 2>/dev/null)
if [ "$STATE" = "device" ]; then
adb shell svc usb setFunctions rndis 2>/dev/null
sleep 3
if ip addr show usb0 2>/dev/null | grep -q "inet "; then
logger -t usb-tether "ADB enabled tethering (attempt $attempt)"
exit 0
fi
fi
DELAY=$((DELAY * 2))
done
logger -t usb-tether "ADB tethering gave up after $attempt attempts"
) &
HOTPLUG_EOF
# --- iPhone USB tethering ---
/usr/sbin/usbmuxd -v -U -f >/dev/null 2>&1 &
USB_DEV=""
for _ in $(seq 1 45); do
for dev in /sys/class/net/*; do
name=$(basename "$dev")
case "$name" in
lo|br-lan|eth0|wlan*) continue ;;
esac
driver=$(readlink "$dev/device/driver" 2>/dev/null || true)
if echo "$driver" | grep -qi "ipheth"; then
USB_DEV="$name"
break 2
fi
iface_desc=""
[ -e "$dev/device/interface" ] && iface_desc=$(cat "$dev/device/interface" 2>/dev/null || true)
if echo "$iface_desc" | grep -qi "apple\|iphone"; then
USB_DEV="$name"
break 2
fi
done
sleep 1
done
if [ -z "$USB_DEV" ]; then
for cand in usb0 usb1; do
[ -e "/sys/class/net/$cand" ] && USB_DEV="$cand" && break
done
fi
if [ -n "$USB_DEV" ]; then
uci set network.usbwan=interface
uci set network.usbwan.proto='dhcp'
uci set network.usbwan.device="$USB_DEV"
uci set network.usbwan.metric='20'
for _z in $(uci show firewall 2>/dev/null | grep '=zone' | cut -d. -f2 | cut -d= -f1 || true); do [ "$(uci -q get firewall.$_z.name)" = 'wan' ] && uci del_list firewall.$_z.network='usbwan' 2>/dev/null; uci add_list firewall.$_z.network='usbwan'; break; done
uci commit network
uci commit firewall
ifup usbwan 2>/dev/null || true
echo "USB tethering enabled on $USB_DEV -> usbwan"
else
echo "USB tethering: no USB network device found, skipping" >&2
fi
# --- Travelmate travel router ---
uci set travelmate.global.trm_enabled='1'
uci set travelmate.global.trm_automatic='1'
uci set travelmate.global.trm_captive='1'
uci set travelmate.global.trm_timeout='60'
uci set travelmate.global.trm_retry='5'
uci set travelmate.global.trm_radio='radio0'
uci commit travelmate
/etc/init.d/travelmate enable
/etc/init.d/travelmate restart
echo "Travelmate configured: auto-connect on radio0"
# --- WireGuard VPN client ---
uci set network.wg0=interface
uci set network.wg0.proto='wireguard'
uci set network.wg0.private_key='generate'
uci set network.wg0.addresses='10.67.0.2/32'
uci set network.wg0_peer=wireguard_wg0
uci set network.wg0_peer.public_key=''
uci set network.wg0_peer.endpoint_host=''
uci set network.wg0_peer.endpoint_port='51820'
uci set network.wg0_peer.allowed_ips='0.0.0.0/0, ::/0'
uci set network.wg0_peer.route_allowed_ips='1'
uci set network.wg0_peer.persistent_keepalive='25'
# --- Cleanup stale anonymous WireGuard firewall sections ---
while uci show firewall 2>/dev/null | grep -q "name='vpn'"; do _s=$(uci show firewall 2>/dev/null | grep "name='vpn'" | head -1 | cut -d. -f2 | cut -d= -f1); uci delete "firewall.$_s" 2>/dev/null; done; true
while uci show firewall 2>/dev/null | grep -q "dest='vpn'"; do _s=$(uci show firewall 2>/dev/null | grep "dest='vpn'" | head -1 | cut -d. -f2 | cut -d= -f1); uci delete "firewall.$_s" 2>/dev/null; done; true
while uci show firewall 2>/dev/null | grep -q "name='KillSwitch-Reject-NonVPN'"; do _s=$(uci show firewall 2>/dev/null | grep "name='KillSwitch-Reject-NonVPN'" | head -1 | cut -d. -f2 | cut -d= -f1); uci delete "firewall.$_s" 2>/dev/null; done; true
# --- WireGuard firewall zone + forwarding ---
uci set firewall.wg_client_vpn=zone
uci set firewall.wg_client_vpn.name='vpn'
uci set firewall.wg_client_vpn.input='REJECT'
uci set firewall.wg_client_vpn.output='ACCEPT'
uci set firewall.wg_client_vpn.forward='REJECT'
uci set firewall.wg_client_vpn.masq='1'
uci set firewall.wg_client_vpn.mtu_fix='1'
uci set firewall.wg_client_vpn.network='wg0'
uci set firewall.wg_client_fwd=forwarding
uci set firewall.wg_client_fwd.src='lan'
uci set firewall.wg_client_fwd.dest='vpn'
uci set firewall.wg_client_killswitch=rule
uci set firewall.wg_client_killswitch.name='KillSwitch-Reject-NonVPN'
uci set firewall.wg_client_killswitch.src='lan'
uci set firewall.wg_client_killswitch.dest='wan'
uci set firewall.wg_client_killswitch.proto='all'
uci set firewall.wg_client_killswitch.target='REJECT'
uci commit network
uci commit firewall
/etc/init.d/network restart
echo 'WireGuard client configured: :51820'
i=0; while [ $i -lt 30 ]; do if wg show wg0 2>/dev/null | grep -q 'latest handshake'; then echo 'WG kill-switch: tunnel verified'; exit 0; fi; sleep 1; i=$((i+1)); done; echo 'WG kill-switch: tunnel failed — removing kill switch to restore WAN'; uci delete firewall.wg_client_killswitch; uci commit firewall; fw4 restart
# --- WireGuard VPN server ---
uci set network.wg0=interface
uci set network.wg0.proto='wireguard'
uci set network.wg0.private_key=''
uci set network.wg0.listen_port='51820'
uci add_list network.wg0.addresses='10.1.99.1/24'
while uci show firewall 2>/dev/null | grep -q "name='vpn'"; do _s=$(uci show firewall 2>/dev/null | grep "name='vpn'" | head -1 | cut -d. -f2 | cut -d= -f1); uci delete "firewall.$_s" 2>/dev/null; done; true
while uci show firewall 2>/dev/null | grep -q "name='Allow-WireGuard'"; do _s=$(uci show firewall 2>/dev/null | grep "name='Allow-WireGuard'" | head -1 | cut -d. -f2 | cut -d= -f1); uci delete "firewall.$_s" 2>/dev/null; done; true
uci set firewall.wg_server_vpn=zone
uci set firewall.wg_server_vpn.name='vpn'
uci set firewall.wg_server_vpn.input='ACCEPT'
uci set firewall.wg_server_vpn.output='ACCEPT'
uci set firewall.wg_server_vpn.forward='REJECT'
uci set firewall.wg_server_vpn.masq='1'
uci set firewall.wg_server_vpn.mtu_fix='1'
uci set firewall.wg_server_vpn.network='wg0'
uci set firewall.wg_server_fwd_lan=forwarding
uci set firewall.wg_server_fwd_lan.src='vpn'
uci set firewall.wg_server_fwd_lan.dest='lan'
uci set firewall.wg_server_fwd_wan=forwarding
uci set firewall.wg_server_fwd_wan.src='vpn'
uci set firewall.wg_server_fwd_wan.dest='wan'
uci set firewall.wg_server_allow=rule
uci set firewall.wg_server_allow.name='Allow-WireGuard'
uci set firewall.wg_server_allow.src='wan'
uci set firewall.wg_server_allow.dest_port='51820'
uci set firewall.wg_server_allow.proto='udp'
uci set firewall.wg_server_allow.target='ACCEPT'
uci commit network
uci commit firewall
/etc/init.d/network restart
echo "WireGuard server configured: port 51820, subnet 10.1.99.1/24"