Skip to content

Instantly share code, notes, and snippets.

@AzimsTech
Last active April 9, 2025 16:24
Show Gist options
  • Save AzimsTech/86da77ec0e5da6345ee0d266aef12844 to your computer and use it in GitHub Desktop.
Save AzimsTech/86da77ec0e5da6345ee0d266aef12844 to your computer and use it in GitHub Desktop.
Installing and Using OpenWrt

Auto USB Tethering on OpenWrt

Objective

Automatically enable USB tethering (RNDIS) when a USB device is connected to OpenWrt.

Steps

  1. Install ADB (if not installed)

    opkg update
    opkg install adb
  2. Create Hotplug Script

     cat << 'EOF' > /etc/hotplug.d/usb/11-auto-tethering
     #!/bin/sh
     logger "USB tethering triggered for device: $PRODUCT"
     sleep 2  # Allow time for recognition
     adb shell svc usb setFunctions rndis
     EOF
  3. Test the Script

    • Plug in a USB device

    • Check logs:

      logread -f
  4. Ensure ADB is Running

    adb start-server
    adb devices

Troubleshooting

  • If adb devices shows "unauthorized," allow USB debugging on the connected device.

  • If the script does not trigger, verify the hotplug system is working:

    echo '#!/bin/sh
    logger "Hotplug triggered: $PRODUCT"' > /etc/hotplug.d/usb/10-test
    chmod +x /etc/hotplug.d/usb/10-test

    Then check logs after reconnecting the USB device.

Conclusion

This setup ensures that USB tethering (RNDIS) is automatically enabled whenever a compatible device is connected to OpenWrt.

⬆️ Go to top

#!/bin/sh
# Updates all `aql_txq_limit` values to user-specified choice ('latency', 'balanced' or 'bandwidth').
# source: https://gist.github.com/Fail-Safe/536e5aa3864ee54078d17bf54b7d76e7
argc() { argc=$#; }
if [ "$#" -ne 1 ]; then
echo "Usage: Enter your AQL preference as 'latency', 'balanced', 'bandwidth', or an integer value for aql_txq_limit." >&2
exit 1
fi
aql_txqs=$(find /sys/ -name 'aql_txq_limit')
argc $aql_txqs
if [ "$argc" -eq 0 ]; then
echo "Error: No AQL tx queues found."
exit 1
fi
aql_txq_limit=$(echo "$1" | awk '{print tolower($0)}')
if [ "$aql_txq_limit" == "latency" ]; then
aql_txq_limit=1500
elif [ "$aql_txq_limit" == "balanced" ]; then
aql_txq_limit=5000
elif [ "$aql_txq_limit" == "bandwidth" ]; then
aql_txq_limit=15000
elif [ "$aql_txq_limit" -eq "$aql_txq_limit" ] 2>/dev/null; then
echo -e "\nInfo: Valid integer value provided."
else
echo "Error: Invalid AQL preference provided. Enter your AQL preference as 'latency', 'balanced', 'bandwidth', or an integer value for aql_txq_limit."
exit 1
fi
for aql_txq in $aql_txqs; do
echo -e "\n>> Device setting: $aql_txq <<"
echo "Before:"
cat "$aql_txq"
for ac in 0 1 2 3; do echo $ac $aql_txq_limit $aql_txq_limit > "$aql_txq"; done
echo -e "\nAfter:"
cat "$aql_txq"
done

OpenWrt config

=== Update root password =====================

echo 'Updating root password'
NEWPASSWD=123
passwd <<EOF
$NEWPASSWD
$NEWPASSWD
EOF

=== Update hostname =====================

HOSTNAME="LiNKSYS"
uci set system.@system[0].hostname=$HOSTNAME
uci set network.lan.hostname="`uci get system.@system[0].hostname`"
uci commit system
/etc/init.d/system reload

=== Set up the WAN (eth0) interface ==================

PPPOE_USERNAME=xxxxxxxxx@unifi
PPPOE_PASSWORD=xxxxxxxxxxxxx
DNS_1=1.1.1.1
DNS_2=8.8.8.8
DNS6_1=2606:4700:4700::1111
DNS6_2=2001:4860:4860::8888
uci set network.wan.proto='pppoe'
uci set network.wan.username=$PPPOE_USERNAME
uci set network.wan.password=$PPPOE_PASSWORD
uci set network.wan.device='wan.500'
uci set network.wan.ipv6='1'
uci set network.wan.peerdns='0'
uci set network.wan.dns="$DNS_1 $DNS_2"
uci set network.wan6.proto='dhcpv6'
uci set network.wan6.device='@wan'
uci set network.wan6.peerdns='0'
uci set network.wan6.dns="$DNS6_1 $DNS6_2"
uci commit network
ifup wan
echo 'Waiting for link to initialize'
sleep 20

=== Update the software packages =============

opkg update                # retrieve updated packages
opkg install luci-app-sqm  # install the SQM modules to get fq_codel etc
opkg remove wpad-basic-wolfssl  # remove the non-mesh version of wpad
opkg install wpad-mesh-wolfssl  # Install the mesh supporting version

=== Set the Time Zone ========================

TIMEZONE='<+08>-8'
ZONENAME='Asia/Kuala Lumpur'
echo 'Setting timezone to' $TIMEZONE
uci set system.@system[0].timezone="$TIMEZONE"
echo 'Setting zone name to' $ZONENAME 
uci set system.@system[0].zonename="$ZONENAME"
uci commit system
/etc/init.d/system reload

/etc/config/network

uci set network.wan.proto='pppoe'
uci set network.wan.username='xxxxxxxxx@unifi'
uci set network.wan.password='xxxxxxxxxxxxx'
uci set network.wan.device='wan.500'
uci set network.wan.ipv6='1'
uci set network.wan.peerdns='0'
uci set network.wan.dns='8.8.8.8' '8.8.4.4'
uci set network.wan6.proto='dhcpv6'
uci set network.wan6.device='@wan'
uci set network.wan6.peerdns='0'
uci set network.wan6.dns='2001:4860:4860::8888 2001:4860:4860::8844'
uci commit network

/etc/config/system

uci set system.@system[0].hostname='LiNKSYS'
uci set system.@system[0].zonename='Asia/Kuala Lumpur'
uci set system.@system[0].timezone='<+08>-8'
uci commit system

⬆️ Go to top

DNS Over TLS on OpenWrt

# Install packages
opkg update; opkg install stubby
 
# Enable DNS encryption
service dnsmasq stop
uci set dhcp.@dnsmasq[0].noresolv="1"
uci set dhcp.@dnsmasq[0].localuse="1"
uci -q delete dhcp.@dnsmasq[0].server
uci -q get stubby.global.listen_address \
| sed -e "s/\s/\n/g;s/@/#/g" \
| while read -r STUBBY_SERV
do uci add_list dhcp.@dnsmasq[0].server="${STUBBY_SERV}"
done
uci commit dhcp
service dnsmasq start

More on openwrt.org/docs/guide-user/services/dns/dot_dnsmasq_stubby

⬆️ Go to top

Tuning IRQ affinity on OpenWrt

Install Irqbalance

opkg update && opkg install irqbalance

Enable

vi /etc/config/irqbalance

option enabled '0' ➑️ '1'

/etc/init.d/irqbalance start # start the daemon

Identify your system's IRQs and their current distribution:

cat /proc/interrupts # Get snapshot of current IRQs

Example:

root@OpenWrt:~# cat /proc/interrupts
           CPU0       CPU1       CPU2       CPU3
  8:    1787212    4591467   13156803     901155  MIPS GIC Local   1  timer
  9:     652247          0          0          0  MIPS GIC  63  IPI call
 10:          0    7833134          0          0  MIPS GIC  64  IPI call
 11:          0          0    5796117          0  MIPS GIC  65  IPI call
 12:          0          0          0   20046278  MIPS GIC  66  IPI call
 13:       7886          0          0          0  MIPS GIC  67  IPI resched
 14:          0       5147          0          0  MIPS GIC  68  IPI resched
 15:          0          0       4509          0  MIPS GIC  69  IPI resched
 16:          0          0          0     442959  MIPS GIC  70  IPI resched
 17:          0          0          0          0  MIPS GIC  19  1e000600.gpio-bank0, 1e000600.gpio-bank1, 1e000600.gpio-bank2
 18:         14          0          0          0  MIPS GIC  33  ttyS0
 19:   11813052          0          0          0  MIPS GIC  10  1e100000.ethernet
 20:          0          0          0          0  MIPS GIC  30  mt7530
 21:          0          0          0          0    mt7530   0  mt7530-0:00
 22:          0          0          0          0    mt7530   1  mt7530-0:01
 23:          0          0          0          0    mt7530   2  mt7530-0:02
 24:          0          0          0          0    mt7530   3  mt7530-0:03
 25:          0          0          0          0  mt7621-gpio  15  keys
 26:          0          0          0          0  mt7621-gpio  18  keys
 27:          0          0          0          0  mt7621-gpio   7  keys
 28:          0          0          0          0  MIPS GIC  29  xhci-hcd:usb1
 29:          0          0          0          0  MIPS GIC  26  1e004000.crypto
 30:    3644079          0          0          0  MIPS GIC  11  mt7615e
 31:    8137280          0          0          0  MIPS GIC  31  mt7615e
ERR:     308656

Tuning IRQ affinity persistently

touch /etc/hotplug.d/net/50-net-smp-affinity     # Create script
vi /etc/hotplug.d/net/50-net-smp-affinity        # Edit script
chmod +x /etc/hotplug.d/net/50-net-smp-affinity  # Make script executable

Add your IRQ tuning commands to the file:

/etc/hotplug.d/net/50-net-smp-affinity

#!/bin/sh

# IRQ tuning commands
echo "0" > /proc/irq/19/smp_affinity_list  # Ethernet
echo "1" > /proc/irq/30/smp_affinity_list  # Wireless NIC (mt7615e)
echo "2" > /proc/irq/31/smp_affinity_list  # Wireless NIC (mt7615e)

Research

⬆️ Go to top

OpenWrt Installation and Configuration on D-LINK DIR-882-A1

Configuration through OpenWrt LuCI web interface

  • Change to DHCP mode after the router is restarted
  • The gateway by default is http://192.168.1.1 without password
  • System
    • Administration
      • change router admin password
      • modify interface of SSH access to LAN
      • SSH Keys
        • past the content of your public key file. It will be a long string starting with ssh-rsa …
  • Network > Wireless > 2.4G AP & 5G AP
    • Device Configuration
      • Advance Settings: modify country code
    • Interface Configuration
      • General Setup: modify ESSID
      • Wireless Security
        • Encryption: WPA2-PSK
        • Cipher: Force CCMP
        • Key: Your Wi-Fi Password
      • Advanced Settings
        • uncheck Disassociate On Low Acknowledgement
        • check Disable Inactivity Polling
        • Time interval for rekeying GTK: 3600
  • Network > Wireless > 5G AP > Device Configuration
    • Operating frequency
      • Mode: AC
      • Channel: 36
      • Width 80mhz
  • Network > Wireless: Save & Apply
  • Network > Interface: modify gateway to 192.168.0.1 if 192.168.1.1 has conflict with upstream
  • Network > Interface: Save & Apply
  • Network > Firewall > General Settings
    1. Routing/NAT Offloading
      • check Software flow offloading
      • check Hardware flow offloading
    2. Save & Apply

Configure PPPoE

  1. Network> Interfaces > Devices: Add device configuration
    1. Select VLAN (802.1q) as device type
    2. Select WAN as base device
    3. Introduce 20 in VLAN ID 20 (This configuration depends on the operator)
    4. uncheck β€œEnable IPv6”
    5. Save
    6. Save & apply
  2. Network> Interfaces > Interface: click edit on WAN configuration
    1. Change protocol to PPPoE
    2. Select Software VLAN wan.20 as device
    3. Introduce PPPoE username and password
    4. Save
    5. Save & apply

⬆️ Go to top

Mangling TTL for Mobile Hotspot

This set of commands configures nftables to set the TTL for IPv4 and Hop Limit for IPv6 to 65 on outgoing packets through eth1. It excludes ICMPv6 NDP traffic to preserve IPv6 functionality.

# Define the interface name
DEVICE="eth1"

# Create the nftables rule file
cat <<EOF > /etc/nftables.d/11-mangle-ttl.nft
chain mangle_postrouting {
    type filter hook postrouting priority mangle; policy accept;

    # Modify TTL for IPv4 packets
    oifname $DEVICE ip ttl set 65 accept

    # Accept ICMPv6 traffic
    oifname $DEVICE meta l4proto ipv6-icmp accept

    # Modify Hop Limit for non-ICMPv6 IPv6 packets
    oifname $DEVICE ip6 hoplimit set 65 accept
}
EOF

# Reload nftables and restart the firewall to apply changes
nft flush ruleset
service firewall restart

⬆️ Go to top

Copying Files between OpenWrt and Windows

[A] Copy Files from OpenWrt to Windows

scp -O root@source_host:source_path destination_path

  • source_host: Router's IP or hostname.
  • source_path: File path to copy.
  • destination_path: Computer's destination path.

Example:

scp -O root@openwrt.lan:/etc/config/sqm C:\Users\AzimsTech\Desktop\sqm

[B] Copy Files from Windows to OpenWrt

Example:

scp -O source_path root@destination_host:destination_path

  • source_path: File path to copy.
  • destination_host: Router's IP or hostname.
  • destination_path: Router's destination path.

Example:

scp -O C:\Users\AzimsTech\Desktop\sysupgrade.bin root@openwrt.lan:/tmp/

⬆️ Go to top

Populate Host Names in Associated Stations to Secondary AP

Secondary OpenWrt Device

  1. Create .ssh directory for root user

     mkdir -p ~/.ssh
  2. Create SSH keys on the secondary device

    dropbearkey -t rsa -f ~/.ssh/id_dropbear
  3. Get generated public key from this command & Copy that to clipboard

    dropbearkey -y -f ~/.ssh/id_dropbear

    Example output:

    Public key portion is:
    ssh-rsa AAAAB3NzaC1yc2EAdrgdftergdsfgdfgdfgdfgdfgdfgdfgJOYPF6nc41DUWDQdRrv8Ihe/zINq5CaFOsysL3LNOg90C9uDYRIp89nq9ydUIrwvjz9r8U/7HFOkLX6YQUevUZHxEyUexhWRSBLbnoQSKLHlB5WhodghdfgdfgdfgdfgdfgdfgfdgdfgfdgdfasdaaedadfasEUxiDTj74l0dqLpCCM1r9BcQd12hvQwfHvbMAcY/7l3Wb5fdAvXI5mMIXXzWPkLhSLHP1Hw1trEmuUeL2rie+WzSjaOGMzVDjOpEaZD0dT7Ib9yDwem8UDMPFuXnNmsUvpxNHakWbw+465uxlyeAzL root@VM-router
    Fingerprint: sha1!! ec:66:c1:57:92:c1:ec:66:c1:57:92:c1:c7:9e:71:50:25:65:61:53:dd
  4. Add cron jobs on the primary device to copy /tmp/dhcp.leases from primary devices

    (crontab -l ; echo "*/5 * * * * scp [email protected]:/tmp/dhcp.leases /tmp/dhcp.leases")| crontab -

Primary OpenWrt Device

  1. Add generated publickey from secondary device using this command here:

    echo "Paste that public key here " >> /etc/dropbear/authorized_keys

⬆️ Go to top

Easy Qosify configuration

opkg update; opkg install qosify
uci set qosify.wan.bandwidth_up='50mbit'
uci set qosify.wan.bandwidth_down='100mbit'
uci set qosify.wan.disabled='0'
uci commit qosify
/etc/init.d/qosify start

⬆️ Go to top

# /etc/config/sqm
config queue 'eth1'
option enabled '1'
option interface 'pppoe-wan'
option download '95000'
option upload '50000'
option qdisc 'fq_codel'
option script 'simplest_tbf.qos' # fq_codel + simplest_tbf are suitable for slow cpu
option linklayer 'ethernet'
option debug_logging '0'
option verbosity '5'
option overhead '50' # 50 = 38 bytes ethernet overhead + 4 bytes VLAN overhead + 8 bytes pppoe overhead

Configure OpenWrt Using uci-defaults

=== Example of creating uci-defaults script for TM Unifi ISP on D-Link DIR-2150-A1 ===

cat << "EOF" > /etc/uci-defaults/99-custom

#!/bin/sh

root_password='REDACTED'
lan_ip='192.168.0.1'
ssid='REDACTED'
ssid_key='REDACTED'
pppoe_name='REDACTED'
pppoe_key='REDACTED'

# root passwd
if [ -n "$root_password" ]; then
  (echo "$root_password"; sleep 1; echo "$root_password") | passwd > /dev/null
fi

# system
uci set system.@system[0].hostname='OpenWrt'
uci set system.@system[0].zonename='Asia/Kuala Lumpur'
uci set system.@system[0].timezone='<+08>-8'
uci del system.ntp.server
uci add_list system.ntp.server='my.pool.ntp.org'
uci add_list system.ntp.server='sg.pool.ntp.org'
uci commit system

# network
uci set network.lan.ipaddr="$lan_ip"
uci set network.lan.gateway='192.168.0.1'
uci set network.lan.ip6assign='64'
uci set network.lan.hostname="`uci get system.@system[0].hostname`"

uci set network.wan.proto='pppoe'
uci set network.wan.device='wan.500'
uci set network.wan.username="$pppoe_name"
uci set network.wan.password="$pppoe_key"
uci set network.wan.ipv6='1'

uci add_list network.wan.dns='1.1.1.1'
uci add_list network.wan.dns='1.0.0.1'
uci set network.wan.peerdns='0'

uci set network.wan6.device='@wan'
uci add_list network.wan6.dns='2606:4700:4700::1111'
uci add_list network.wan6.dns='2606:4700:4700::1001'
uci set network.wan6.peerdns='0'

uci commit network

# wireless
uci set  wireless.@wifi-device[0].country='MY'
uci set wireless.@wifi-device[0].disabled='0'

uci set wireless.@wifi-iface[0].mode='ap'
uci set wireless.@wifi-iface[0].ssid="${ssid}-2.4G@unifi"
uci set wireless.@wifi-iface[0].encryption='psk2+aes'
uci set wireless.@wifi-iface[0].key="$ssid_key"

uci set  wireless.@wifi-device[1].country='MY'
uci set wireless.@wifi-device[1].disabled='0'

uci set wireless.@wifi-iface[1].mode='ap'
uci set wireless.@wifi-iface[1].ssid="${ssid}-5G@unifi"
uci set wireless.@wifi-iface[1].encryption='psk2+aes'
uci set wireless.@wifi-iface[1].key="$ssid_key"
uci set wireless.@wifi-iface[1].wds='1'
uci commit wireless

# dhcp

echo "All done!"

EOF

reboot

=== Example of creating uci-defaults script for WDS Station on D-Link DIR-842 ===

cat << "EOF" > /etc/uci-defaults/99-custom

#!/bin/sh

root_password='REDACTED'
lan_ip='192.168.0.2'
ssid='REDACTED'
ssid_key='REDACTED'

# root passwd
if [ -n "$root_password" ]; then
  (echo "$root_password"; sleep 1; echo "$root_password") | passwd > /dev/null
fi

# system
uci set system.@system[0].hostname='DIR842-STA'
uci set system.@system[0].zonename='Asia/Kuala Lumpur'
uci set system.@system[0].timezone='<+08>-8'
uci del system.ntp.server
uci add_list system.ntp.server='my.pool.ntp.org'
uci add_list system.ntp.server='sg.pool.ntp.org'
uci commit system

# network
uci set network.lan.ipaddr="$lan_ip"
uci set network.lan.gateway='192.168.0.1'
uci set network.lan.ip6assign='64'
uci del network.lan.dns
uci add_list network.lan.dns='192.168.0.1'
uci del network.@device[0].ports
uci set network.@device[0].ipv6='0'
uci add_list network.@device[0].ports='eth0.1'
uci add_list network.@device[0].ports='eth0.2'
uci set network.lan.hostname="`uci get system.@system[0].hostname`"
uci commit network

# wireless
uci set  wireless.@wifi-device[0].country='MY'
uci set wireless.@wifi-device[0].disabled='0'

uci set wireless.@wifi-iface[0].mode='sta'
uci set wireless.@wifi-iface[0].ssid="${ssid}-5G@unifi"
uci set wireless.@wifi-iface[0].encryption='psk2+aes'
uci set wireless.@wifi-iface[0].key="$ssid_key"
uci set wireless.@wifi-iface[0].wds='1'
uci commit wireless

# dhcp
uci set dhcp.lan.ignore='1'
uci del dhcp.lan.ra
uci del dhcp.lan.dhcpv6
uci del dhcp.lan.ra_flags
uci del dhcp.lan.ra_slaac
uci commit dhcp

echo "All done!"

EOF

reboot

⬆️ Go to top

UniFi HOME Configuration

IPv6 Relay

uci set dhcp.lan.dhcpv6='relay'
uci set dhcp.lan.ra='relay'
uci set dhcp.lan.ndp='relay'

uci set dhcp.wan6=dhcp
uci set dhcp.wan6.interface='wan6'
uci set dhcp.wan6.ignore='1'
uci set dhcp.wan6.master='1'
uci set dhcp.wan6.ndp='relay'
uci set dhcp.wan6.ra='relay'
uci set dhcp.wan6.dhcpv6='relay'

uci commit dhcp
/etc/init.d/dnsmasq restart
/etc/init.d/odhcpd restart

Fixing IPv6 relay bug

As discussed here: openwrt/odhcpd #193

mkdir /etc/ppp/ip-up.d/

cat <<"EOF"> /etc/ppp/ip-up.d/00-add-ip6-route
#!/bin/sh
[ "$1" = "pppoe-wan" ] || exit 0
ip -6 route add default dev br-lan table 6
ip -6 rule add iif $1 lookup 6
EOF

chmod +x /etc/ppp/ip-up.d/00-add-ip6-route

⬆️ Go to top

USB Tethering

Getting around Hotspot restrictions

Create firewall.user

# Modify usb usb interface name
WAN_DEV="eth1"

# Create the file /etc/config/firewall.user
cat << "EOF" > /etc/config/firewall.user
nft add rule inet fw4 mangle_forward oifname { $WAN_DEV } ip ttl set 65
nft add rule inet fw4 mangle_forward oifname { $WAN_DEV } ip6 hoplimit set 65
EOF

Modify firewall config

uci add firewall include
uci set firewall.@include[-1].path='/etc/config/firewall.user'
uci set firewall.@include[-1].fw4_compatible='1'
uci commit firewall

Restart firewall

/etc/init.d/firewall restart

Install required drivers

opkg update && opkg install luci kmod-usb-net-rndis

To check usb interface name

root@OpenWrt:~# ifconfig
...

eth1      Link encap:Ethernet  HWaddr 76:F1:9B:1B:2F:4D
          inet addr:192.168.130.153  Bcast:192.168.130.255  Mask:255.255.255.0
          inet6 addr: fe80::0000:0000:0000:0000/64 Scope:Link
          inet6 addr: 2405:0000:000:0000:0000:0000:0000:0000/64 Scope:Global
          UP BROADCAST RUNNING MULTICAST  MTU:1400  Metric:1
          RX packets:1189920 errors:0 dropped:0 overruns:0 frame:0
          TX packets:613982 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1536214667 (1.4 GiB)  TX bytes:86055509 (82.0 MiB)

...

In my case eth1 is the interface name for the usb

Uci-defaults script

#!/bin/sh
# Beware! This script will be in /rom/etc/uci-defaults/ as part of the image.

# checks: ensure scripts don't overwrite custom settings
[ "$(uci -q get system.@system[0].zonename)" = "Asia/Kuala Lumpur" ] && exit 0

# log potential errors
exec >/tmp/setup.log 2>&1

#--------------------------------------------------------------------------------
# /etc/config/network
#--------------------------------------------------------------------------------
ROOT_PASS="123"
LAN_IP="192.168.1.1"
WAN_DEV="usb0"
DNS_1="1.1.1.1"
DNS_2="1.0.0.1"
DNS6_1="2606:4700:4700::1111"
DNS6_2="2606:4700:4700::1001"

if [ -n "$ROOT_PASS" ]; then
  (echo "$ROOT_PASS"; sleep 1; echo "$ROOT_PASS") | passwd > /dev/null
fi

uci set network.lan.ipaddr="$LAN_IP"
uci set network.lan.netmask='255.255.255.0'
uci set network.lan.ip6assign='64'

uci set network.wan.device="$WAN_DEV"
uci set network.wan.proto='dhcp'
uci add_list network.wan.dns="${DNS_1}"
uci add_list network.wan.dns="${DNS_2}"
uci set network.wan.peerdns='0'
uci set network.wan.mtu='1400'

uci set network.wan6.device="$WAN_DEV"
uci set network.wan6.proto='dhcpv6'
uci add_list network.wan6.dns="${DNS6_1}"
uci add_list network.wan6.dns="${DNS6_2}"
uci set network.wan6.peerdns='0'
uci set network.wan6.reqaddress='try'
uci set network.wan6.reqprefix='auto'
uci set network.wan6.norelease='1'
uci set network.wan6.mtu='1400'

uci commit network
/etc/init.d/network restart

#--------------------------------------------------------------------------------
# /etc/config/dhcp
#--------------------------------------------------------------------------------
uci set dhcp.lan.dhcpv6='relay'
uci set dhcp.lan.ra='relay'
uci set dhcp.lan.ndp='relay'

uci set dhcp.wan6=dhcp
uci set dhcp.wan6.interface='wan6'
uci set dhcp.wan6.ignore='1'
uci set dhcp.wan6.master='1'
uci set dhcp.wan6.ndp='relay'
uci set dhcp.wan6.ra='relay'
uci set dhcp.wan6.dhcpv6='relay'

uci commit dhcp
/etc/init.d/dnsmasq restart
/etc/init.d/odhcpd restart

#--------------------------------------------------------------------------------
# /etc/config/system
#--------------------------------------------------------------------------------
uci set system.@system[0].hostname='OpenWrt'
uci set system.@system[0].timezone='<+08>-8'
uci set system.@system[0].zonename='Asia/Kuala Lumpur'

uci delete system.ntp.server
uci add_list system.ntp.server='my.pool.ntp.org'
uci add_list system.ntp.server='sg.pool.ntp.org'

uci commit system

#--------------------------------------------------------------------------------
# /etc/config/wireless
#--------------------------------------------------------------------------------
SSID="πŸ’€πŸ”₯πŸ“Ά"
KEY="123123123"

# Retrieve the 2.4GHz RADIO2g index
RADIO2g=$(uci show wireless | grep "\.band='2g'" | cut -d'=' -f1 | cut -d'.' -f2 | sed 's/[^0-9]//g')
if [ -z "$RADIO2g" ]; then
    echo "Error: 2.4GHz RADIO2g not found."
    exit 1
fi

# Configure the 2.4GHz wireless device
uci set wireless.@wifi-device[$RADIO2g].channel='6'
uci set wireless.@wifi-device[$RADIO2g].country='MY'
uci set wireless.@wifi-device[$RADIO2g].disabled='0'

# Configure the wireless interface
uci set wireless.@wifi-iface[$RADIO2g].mode='ap'
uci set wireless.@wifi-iface[$RADIO2g].ssid="$SSID"
uci set wireless.@wifi-iface[$RADIO2g].encryption='psk2'
uci set wireless.@wifi-iface[$RADIO2g].key="$KEY"

uci commit wireless
wifi

cat << "EOF" > /etc/hotplug.d/button/buttons
#!/bin/sh
logger "the button was ${BUTTON} and the action was ${ACTION}"

[ "${BUTTON}" = "wps" ] && [ "${ACTION}" = "pressed" ] && {
    SW="$(uci -q get sqm.eth1.enabled)"
    [ "${SW}" = "1" ] \
        && uci set sqm.eth1.enabled="0" \
        || uci set sqm.eth1.enabled="1"
    /etc/init.d/sqm restart
    [ "${SW}" = "1" ] && echo 0 > /sys/class/leds/green:net/brightness || echo 255 > /sys/class/leds/green:net/brightness
}
EOF


uci commmit
echo "All done!"

Overcoming ISP Restrictions

Some ISPs restrict tethering by detecting TTL values. Adjusting TTL can help bypass these restrictions.

  1. Check your USB device interface:

    ifstatus wan | grep -e l3_device
  2. Add an nftables rule to modify TTL values:

    WAN_DEV="eth1" # or usb0
    cat <<EOF> /etc/nftables.d/12-mangle-ttl-65.nft
    # For forwarded (client) traffic
    chain mangle_forward {
        type filter hook forward priority mangle; policy accept;
        oifname "$WAN_DEV" ip ttl set 65
        oifname "$WAN_DEV" ip6 hoplimit set 65
    }
    
    # For locally generated IPv4 traffic
    chain mangle_postrouting_ipv4 {
        type filter hook postrouting priority mangle; policy accept;
        oifname "$WAN_DEV" ip ttl set 65
    }
    
    chain mangle_postrouting_ipv6 {
        type filter hook postrouting priority mangle; policy accept;
        # Allow critical ICMPv6 neighbor discovery messages to pass unchanged
        ip6 nexthdr ipv6-icmp icmpv6 type { 133, 134, 135, 136, 137 } oifname "$WAN_DEV" counter accept
        # Adjust hoplimit for all other IPv6 traffic on $WAN_DEV
        oifname "$WAN_DEV" ip6 hoplimit set 65
    }
    EOF
  3. Restart the firewall to apply changes:

    service firewall restart
  4. Verify the rule is active:

    nft list ruleset

πŸ” Figuring out real MTU

Finding the correct MTU helps prevent fragmentation and improves network performance.

  1. Install iputils-tracepath:

    opkg update ; opkg install iputils-tracepath
  2. Detect MTU with this command:

    tracepath -b4 www.google.com
    tracepath -b6 www.google.com
  3. Compare the final results and use the smaller MTU to avoid fragmentation issues. Usually, both should be the same.

  4. Set the correct MTU for the USB device. First, confirm the interface name using:

    ifstatus wan | grep -e l3_device

    Then, apply the MTU setting:

    uci set network.wan.mtu='1400'
    uci set network.wan6.mtu='1400'
    uci commit network
  5. Verify the change with:

    ip link show eth1 # or usb0

Research

⬆️ Go to top

Using OpenWrt Image Builder with WSL

  1. Install Ubuntu WSL & reboot the computer

     wsl --install Ubuntu; shutdown -r -t 0
  2. Remove windows path from $PATH in WSL (see why)

    sudo su
    echo -e "[interop]\nappendWindowsPath=false" >> /etc/wsl.conf
    exit
  3. Install build requirements for Ubuntu

    sudo apt update && sudo apt dist-upgrade
    sudo apt install build-essential clang flex bison g++ gawk \
    gcc-multilib g++-multilib gettext git libncurses-dev libssl-dev \
    python3-distutils rsync unzip zlib1g-dev file wget
  4. Download image builder based on your target & extract it

    wget https://downloads.openwrt.org/releases/23.05.2/targets/ath79/generic/openwrt-imagebuilder-23.05.2-ath79-generic.Linux-x86_64.tar.xz
    tar -J -x -f openwrt-imagebuilder-*.tar.xz
    cd openwrt-imagebuilder-*/
  5. (Optional) Create uci-defaults script

    mkdir -p files/etc/uci-defaults/
    cat << "EOF" > files/etc/uci-defaults/99-custom
    uci set wireless.@wifi-device[0].disabled="0"
    uci set wireless.@wifi-iface[0].disabled="0"
    uci set wireless.@wifi-iface[0].ssid="OpenWrt"
    uci set wireless.@wifi-iface[0].key="changemeplox"
    uci set wireless.@wifi-iface[0].encryption="psk2"
    uci commit wireless
    EOF

    ⬆️ More examples here

  6. Start building image

    make image \
    PROFILE="dlink_dir-842-c2" \
    PACKAGES="luci ath10k-firmware-qca9888 kmod-ath10k -ppp -ppp-mod-pppoe -ath10k-firmware-qca9888-ct -kmod-ath10k-ct" \
    FILES="files" \
    DISABLED_SERVICES="dnsmasq firewall odhcpd"

    Run make info to list all avaiable PROFILE.
    See detailed help for more build confirguration.

  7. Copy & paste built image to desired windows directory

     cp -r bin /mnt/d
  8. Cleaning up

    make clean

⬆️ Go to top

Verify SHA256 checksums in PowerShell

(Get-FileHash '.\path\to\foo.zip').Hash -eq (Get-Content .\expected-hash.sha256)

Example

(Get-FileHash .\openwrt-23.05.0-ramips-mt7621-dlink_dir-882-a1-squashfs-sysupgrade.bin).Hash -eq "452b69cc96aff64150e39396e174530ff6634a49b888c450cb713ad0d891f23e"

⬆️ Go to top

Practical Cheat Sheet for BusyBox vi

# Editing
i/a    β†’ Insert/Append
dd     β†’ Delete line
yy     β†’ Copy line
p/P    β†’ Paste
dG     β†’ Delete to end of file
:%s/old/new/g β†’ Replace all "old" with "new" 

# Navigation
G      β†’ End of file
gg     β†’ Start of file
:n     β†’ Jump to line n

# File Operations
:wq    β†’ Save and quit
:q!    β†’ Quit without saving
:r file β†’ Insert file contents

# Shell & System  
Ctrl+Z β†’ Suspend vi (resume with `fg`)  
:!cmd  β†’ Run shell command (e.g., `:!ls`)  
Ctrl+C β†’ Cancel operation (e.g., interrupt search)  

Full Version

# Editing  
i/a    β†’ Insert/Append  
dd     β†’ Delete line  
dw     β†’ Delete word  
dG     β†’ Delete to end of file  
d$     β†’ Delete to end of line (or `D`)  
yy     β†’ Copy line  
p/P    β†’ Paste after/before cursor  
x      β†’ Delete character under cursor  
r      β†’ Replace character (e.g., `rx` replaces with "x")  
~      β†’ Toggle case of character (uppercase ↔ lowercase)  
J      β†’ Join current line with next line  
.      β†’ Repeat last command  
:%s/old/new/g β†’ Replace all "old" with "new"  

# Navigation  
G      β†’ End of file  
gg     β†’ Start of file  
:n     β†’ Jump to line `n` (e.g., `:5`)  
'x     β†’ Jump to mark "x" (set with `mx`)  
w      β†’ Jump to next word  
b      β†’ Jump to previous word  

# Search  
/text  β†’ Search forward for "text"  
?text  β†’ Search backward for "text"  
n      β†’ Next match  
N      β†’ Previous match  

# File Operations  
:wq    β†’ Save and quit (or `ZZ`)  
:q!    β†’ Quit without saving  
:r file β†’ Insert file contents at cursor  
:w!    β†’ Force write (overrides read-only)  

# Buffers & Marks  
"ayy   β†’ Yank line into buffer "a"  
"ap    β†’ Paste from buffer "a"  
mx     β†’ Mark current position as "x"  

# Settings  
:set ic β†’ Case-insensitive search  
:set noic β†’ Case-sensitive search  
:set list β†’ Show invisible characters (e.g., tabs as `^I`)  

# Shell & System  
Ctrl+Z β†’ Suspend vi (resume with `fg`)  
:!cmd  β†’ Run shell command (e.g., `:!ls`)  
Ctrl+C β†’ Cancel operation (e.g., interrupt search)  

⬆️ Go to top

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment