From Segfault
Jump to: navigation, search


Please refer to the hardware model on how to install OpenWRT.


If, for some reason we have to install from trunk, we may have to install some LuCI modules:

# Required: egrep, wget, ssh, and scp, signify

# Adjust if needed

if [ $# -ne 1 ]; then
    echo "Usage: $0 [arch]"
    exit 1

packages_base="liblua lua libuci-lua libubus libubus-lua uhttpd rpcd"
packages_luci="luci-base luci-lib-ip luci-lib-nixio luci-theme-bootstrap luci-mod-admin-full luci-lib-jsonc"

mkdir -p "$tmpdir" && cd "$tmpdir"

echo "### Getting base/packages..."
wget -Nq "${url}base/Packages"
for pkg in $packages_base; do
    pkgfile="$(egrep -oe " ${pkg}_.+" Packages | tail -c +2)"
    wget -Nq "$pkgurl"

echo "### Getting luci/packages..."
wget -Nq "${url}luci/Packages"
for pkg in $packages_luci; do
    pkgfile="$(egrep -oe " ${pkg}_.+" Packages | tail -c +2)"
    wget -Nq "$pkgurl"

echo "### Getting luci..."
wget -Nq "${url}luci"
for pkg in $packages_luci; do
    pkgfile="$(egrep -oe " ${pkg}_.+" Packages | tail -c +2)"
    wget -Nq "$pkgurl"

scp -r "$tmpdir" "${user}@${ip_address}":/tmp/
ssh "${user}@${ip_address}" opkg install /tmp/luci-offline-packages/*.ipk
ssh "${user}@${ip_address}" rm -rf /tmp/luci-offline-packages/

ssh "${user}@${ip_address}" "/etc/init.d/uhttpd start; /etc/init.d/uhttpd enable"

Some devices require special drivers and firmware too:

opkg install ath10k-firmware-qca988x kmod-ath10k

Being trunk, some packages may not work properly yet:



After logging in, the root password can be set with:

passwd -a sha512

We specify a (supported)[1] hash function, otherwise the password is stored as an (unsalted) MD5 hash:

$ grep ^root /etc/shadow


Install some essential packages:

opkg install ca-certificates curl diffutils dnscrypt-proxy haveged iftop iperf nrpe rsync script-utils snmpd vnstat



WAN interface

For some reason, dnsmasq is listening on the WAN interface[2] too, answering DNS lookups to the entire internet and even gives out internal records. Instead of creating a firewall rule[3] we just disable dnsmasq on the WAN interface:

$ grep ^interface /etc/dnsmasq.conf 

Or, in /etc/config/dhcp:

config dnsmasq
       option interface 'lo br-lan'

Restart DNSmasq:

$ /etc/init.d/dnsmasq restart

With that in place, dnsmasq only listens on loopback and the local network interface.


The documentation states that it is possible to add a CNAME resource record:

$ grep -A2 cname /etc/config/dhcp 
config 'cname'
       option cname 'mail'
       option target 'server'

However, as of 10.03.1 this feature does not seem to be implemented. Patching the initscript helps:

--- /etc/init.d/dnsmasq.orig    Wed Nov 23 17:13:22 2011
+++ /etc/init.d/dnsmasq Sun Jul 15 16:43:44 2012
@@ -346,6 +346,19 @@
+dhcp_cname_add() {
+       local cfg="$1"
+       local cname target
+       config_get cname "$cfg" cname
+       [ -n "$cname" ] || return 0
+       config_get target "$cfg" target
+       [ -n "$target" ] || return 0
+       append args "--cname=${cname},${target}"
 start() {
        include /lib/network
@@ -367,6 +380,7 @@
        config_foreach dhcp_subscrid_add subscrid
        config_foreach dhcp_domain_add domain
        config_foreach dhcp_add dhcp
+       config_foreach dhcp_cname_add cname
        # add own hostname
        [ -z "$lanaddr" ] || {


DNSCrypt secures the client-server communication for DNS lookups. For trunk, installation is quite straightforward:

opkg update
opkg install dnscrypt-proxy

Configure /etc/config/dnscrypt-proxy like this:

config dnscrypt-proxy ns1
       option address ''
       option port '5353'
       option resolver 'fvz-anyone'
       # option resolvers_list '/usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv'
       option ephemeral_keys '1'
  • The resolvers_list is hosted in a Github repository and should already be in place.
  • The OpenNIC project also lists public DNS servers, some with DNSCrypt enabled.
  • The resolver is the name of a group of public DNS servers in the resolvers_list. One group per dnscrypt-proxy instance can be specified.
$ cut -d, -f1 /usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv | cut -d- -f1 | sort | uniq -c | sort -n | tail -5
     4 adguard
     4 cisco
     4 fvz
    12 cs
    35 d0wn

Now that dnscrypt-proxy is configured, we need to configure dnsmasq too. In /etc/config/dhcp, change the following:

config dnsmasq
       option domainneeded '1'
       option boguspriv '1'
       option localise_queries '1'
       option rebind_protection '1'
       option rebind_localhost '1'
       option expandhosts '1'
       option authoritative '1'
       option readethers '1'
       option leasefile '/tmp/dhcp.leases'
#      option resolvfile '/tmp/'
       option noresolv '1'
       option localservice '1'
       option local '/lan/'
       option domain 'lan'
       option nonwildcard '1'
       list server ''
       list server '/'
       list interface 'br-lan'
       list notinterface 'eth0'



Dynamic DNS

The DDNS Client configuration changed quite a bit over the last OpenWRT versions, the following should be valid for OpenWRT 15.05.1.

Install the DDNS client and the LuCI frontend:

opkg install ddns-scripts luci-app-ddns

Configure our DDNS service:

uci set ddns.myddns_ipv4.service_name=''     # Must match a name from /usr/lib/ddns/services
uci set ddns.myddns_ipv4.use_https='1'
uci set ddns.myddns_ipv4.domain=''
uci set ddns.myddns_ipv4.username='joe'
uci set ddns.myddns_ipv4.password='s3cr3t'
uci set ddns.myddns_ipv4.check_interval='10'
uci set ddns.myddns_ipv4.check_unit='hours'
uci set ddns.myddns_ipv4.enabled='1'

uci set ddns.myddns_ipv6.service_name=''     # Must match a name from /usr/lib/ddns/services
uci set ddns.myddns_ipv6.use_https='1'
uci set ddns.myddns_ipv6.domain=''
uci set ddns.myddns_ipv6.username='joe'
uci set ddns.myddns_ipv6.password='s3cr3t'
uci set ddns.myddns_ipv6.check_interval='10'
uci set ddns.myddns_ipv6.check_unit='hours'
uci set ddns.myddns_ipv6.enabled='1'
uci commit ddns

With the last command, /etc/config/ddns will be written. The DDNS daemon will be started with the next reboot or can be started as such:

. /usr/lib/ddns/
start_daemon_for_all_ddns_sections "wan"

The wan parameter is the ip_network value in /etc/config/ddns. Let's see if this worked:

$ nslookup
Address 1:
Address 1:




In earlier OpenWRT versions, /usr/lib/ddns/services had to be tweaked for hosts:[4][5]

""  "[PASSWORD]&address=[IP]"

DynDNS supported[6][7] options like wildcard DNS or MX records[8], but this can only be set online and the OpenWrt DynDNS client must be tought to handle these settings. This can only be done via tweaking /usr/lib/ddns/services:

"" "http://[USERNAME]:[PASSWORD][DOMAIN]&myip=[IP]&wildcard=ON&mx=NOCHG"



We use dnsmasq to block adservers and use a blocklist from

$ wget -O /etc/dnsmasq.adservers ""

$ tail -3 /etc/dnsmasq.conf
conf-file=/etc/dnsmasq.adservers         # Adjust the target address as needed, e.g.
conf-file=/etc/              # address=/.corp/ to blackhole all .corp

$ /etc/init.d/dnsmasq restart

Add a cronjob to update the blocklists

$ crontab -l
0   23 * * 1 /root/bin/ restart


The Pi-hole™ distribution uses several blocklists to generate a single list[9][10], and we could do the same:


Guest WLAN



With OpenWRT 15.05, nrpe appears to be unmaintained[11]. We should built the package manually[12]. In the meantime, we have just copied the package from our backups:



cd ~/backup/router/ && find . -name "*nrpe*" -o -name "check_*" | xargs tar -cf - ) | \
   ssh router "tar -C / -xvf -"

Almost there:

$ ldd /usr/sbin/nrpe                                           # Note: ldd is used to be a shell function!
                                                               # LD_TRACE_LOADED_OBJECTS=1 => not found => not found => not found => /lib/ (0x77a64000) => /lib/ (0x779f7000) => /lib/ (0x77a88000)

Install dependencies:

opkg install libopenssl libwrap

Add nagios user:

echo 'nagios:x:50:' >> /etc/group
echo 'nagios:x:50:50:nagios:/var/run/nagios:/bin/false' >> /etc/passwd
echo 'nagios::16874:0:99999:7:::' >> /etc/shadow

Configure nrpe:

$ grep ^[a-z] /etc/nrpe.cfg

command[check_dummy]=/usr/libexec/nagios/check_dummy 0
command[check_dns]=/usr/libexec/nagios/check_dns -H -s localhost -w 0.1 -c 0.5
command[check_entropy]=/root/bin/ -w 1024 -c 512
command[check_http]=/usr/libexec/nagios/check_http -H localhost -w 0.1 -c 0.5
command[check_load]=/usr/libexec/nagios/check_load -w 4,3,2 -c 5,4,3
command[check_ntp_time]=/usr/libexec/nagios/check_ntp_time -H -w 0.5 -c 1.0
command[check_ssh]=/usr/libexec/nagios/check_ssh -4 router
command[check_softwareupdate_opkg]=/root/bin/ opkg
command[check_users]=/usr/libexec/nagios/check_users -w 3 -c 5

Let's try to start it, and enable it if it works:

$ /etc/init.d/nrpe start
$ ps | grep nrp[e]
5320 nagios    2908 S    /usr/sbin/nrpe -c /etc/nrpe.cfg -d

$ /etc/init.d/nrpe enable


$ sysctl kernel.random.entropy_avail
kernel.random.entropy_avail = 140

Install haveged:

opkg update
opkg install haveged

With that, haveged should already be enabled and running, otherwise:

/etc/init.d/haveged enable
/etc/init.d/haveged start

Now it should look like this:

$ sysctl kernel.random.entropy_avail
kernel.random.entropy_avail = 1393


There's an excellent OpenWrt Howto on how to get IPv6 up & running. Here's the short story:

$ opkg update && opkg install 6in4
Updated list of available packages in /var/opkg-lists/packages.
Installing 6in4 (10-1) to root...
Installing ip (2.6.29-1-2) to root...
Installing kmod-ipv6 ( to root...
Installing kmod-sit ( to root...
Configuring ip.
Configuring kmod-ipv6.
Configuring kmod-sit.
Warning: loading sit will taint the kernel: no license
 See for information about tainted modules
Configuring 6in4.

When using HE, one can just use their "Example Configuration", since they're providing a full OpenWRT configuration:

uci set network.henet=interface
uci set network.henet.proto=6in4
uci set network.henet.peeraddr=
uci set network.henet.ip6addr='2001:123:45:67::8/64'
uci set network.henet.tunnelid=123456
uci set network.henet.username=UserName
uci set network.henet.password='s3cr3t'
uci commit network

uci set firewall.@zone[1].network='wan henet'
uci commit firewall

ifup henet
/etc/init.d/firewall restart

We want to setup routing through this tunnel interface. For HE, we have to use the "Routed IPv6 Prefix" (Routed /64) and add it to our configuration. This prefix can be calculated by incrementing the last digit of the third quad in the tunneling prefix:

$ uci show network.henet.ip6addr

$ uci set network.lan.ip6addr='2001:123:46:67::8/64'
$ uci commit network


MuninLite is a shell script implementing the Munin protocol and providing some Linux specific plugins.

$ opkg install muninlite                    # This will also install xinetd
$ /etc/init.d/xinetd enable

Be sure to add the bind option to xinetd's config, otherwise we'd listen even on the WAN interface:

$ cat /etc/xinetd.d/munin 
service munin
       socket_type     = stream
       protocol        = tcp
       wait            = no
       user            = root
       group           = root
       server          = /usr/sbin/munin-node
       disable         = no
       bind            =

Start xinetd:

$ /etc/init.d/xinetd start

$ echo list | nc localhost 4949 
# munin node at router
cpu if_eth0 if_eth0VLAN0 if_eth0VLAN1 if_br_lan if_err_eth0 if_err_eth0VLAN0 \
if_err_eth0VLAN1 if_err_br_lan  load memory processes uptime interrupts irqstats


Note: NRPE is currently not available for OpenWRT, as it's unmaintained.[13]

opkg update
opkg install nrpe

Configure in /etc/nrpe.cfg, then:

/etc/init.d/nrpe enable
/etc/init.d/nrpe start


opkg install snmpd                         # mini-snmpd can't handle 64-bit counters[14]

Adjust /etc/config/snmpd, e.g.:

config agent
       option agentaddress udp:
config system
       option sysLocation      'UK'
       option sysContact       'root@mailhub'
       option sysName          'router'
#      option sysServices      72
#      option sysDescr         'home router'
#      option sysObjectID      ''

Enable & start snmpd:

/etc/init.d/snmpd enable
/etc/init.d/snmpd start

snmpd should be running now:

# netstat -an | grep :161
udp        0      0*

# ls -l /var/run/snmpd.conf 
-rw-r--r--    1 root     root           430 Dec  9 22:52 /var/run/snmpd.conf


opkg update
opkg install vnstat

With that, vnstat should already be configured and vnstatd should be running:

$ ps | grep vn[s]
5288 root       988 S    /usr/sbin/vnstatd -d

We may want to move the traffic database to a permanent storage[15], so it will be saved across reboots:

$ mv /var/lib/vnstat/ /root/.vnstat
$ cat /etc/vnstat.conf
Interface "eth1"
DatabaseDir "/root/.vnstat"

$ /etc/init.d/vnstat restart

If we need to configure vnstat manually:

$ uci get network.wan.ifname

Our LAN interface is often handled by a bridge:

$  brctl show
bridge name     bridge id               STP enabled     interfaces
br-lan          6fff.2be01a132618       no              eth0.1

Initialize the databases for both the WAN and LAN interface:

vnstat -u -i eth1
vnstat -u -i br-lan

If we decide against running the vnstatd daemon, we'll have to update the database with a cronjob:

$ crontab -l                                          # /etc/crontabs/root
*/5 * * * * /usr/bin/vnstat -u -i eth1
*/5 * * * * /usr/bin/vnstat -u -i br-lan

$ /etc/init.d/cron enable
$ /etc/init.d/cron start



To backup the OpenWrt configuratin[16], use sysupgrade:

sysupgrade --create-backup /tmp/backup-$(uname -n)-$(date +%F).tar.gz

This can be restored via the web interface later on:

System → Backup / Flash Firmware  → Backup / Restore

Or, manually on the command line:

tar -xzvf -C / backup.tar.gz


We want to save some other parts of the system too:

uci show   > uci-show.txt
uci export > uci-export.txt
opkg list-installed > opkg-installed.txt

Backups can be created from the GUI (SystemBackup) or via command line. Since Busybox tar(1) does not support --exclude but only -X (exclude from a file),[17] a backup command will look something like this:

$ ssh router "cat /root/backup.exclude"

$ ssh router "cd / && tar -X /root/backup.exclude -cf - ." | xz -9ec > router-backup.tar.xz

And the other way around, to restore:

xz -dc router-backup.tar.xz | ssh router "cd / && tar -xvf -"


Caution: although upgrading packages is possible[18] via opkg it's not recommended and can be dangerous![19] Use only when you how to reset[20] and debrick[21] your device!

To update all (outdated) packages:

opkg update && opkg list-upgradable

opkg upgrade $(opkg list-upgradable | awk '{print $1}')                        # See the warning above!

Find all updated files:

find /overlay/ -type f -exec ls -ltrd '{}' + | grep "$(date +%b\ \ %-d)"       # May not work, since it's padding the 
                                                                               # days and +%-d may not supported yet.

Note: the -mtime option in OpenWRT's version of BusyBox/findutils was disabled and may not be available. It has been enabled again[22][23] in late 2015:

find /overlay/ -type f -mtime -1 -exec ls -ltrd '{}' +

Find leftover configuration files:

find /etc/ -name "*opkg" -exec ls -lhtrd '{}' +

Sometimes configuration formats have changed and uci throws an error:

uci: Parse error (too many arguments) at line 124, byte 23

Let's find out where the error was generated:

$ for c in /etc/config/*; do uci show ${c#/etc/config/} > /dev/null || echo $c; done
uci: Parse error (too many arguments) at line 124, byte 23

After fixing this configuration file, the error should be gone.



cd /root
opkg list-changed-conffiles                               # Check and maybe add additional files to /etc/sysupgrade.conf
opkg list-installed | awk '{print $1}' | sort > opkg_installed
awk '/^Package:/ {PKG= $2} /^Status: .*user installed/ {print PKG}' /usr/lib/opkg/status | sort > status_installed

After backing up the device once more, start the actual upgrade over a wired connection using the correct image and after verifying its checksum:

sysupgrade -v /tmp/*sysupgrade.bin


opkg list-installed | sort > foo
for p in `awk '!/^lib/ {print $1}' opkg_installed`; do grep -qw $p foo || echo "to be installed: $p"; done

Install missing packages and check for leftover configuration files:

find /etc -name "*opkg"

Enable necessary services again:

for s in haveged snmpd vnstat; do /etc/init.d/$s enable; done
for s in haveged snmpd vnstat; do /etc/init.d/$s start; done


To decommision a router with OpenWRT installed:

  • Reset via Failsafe mode: unplug the power cord, press and hold the reset button, put in the power cord, release the reset button when the DMZ-LED lits up.
> telnet                               # no password required
$ mount_root
switching to jffs2                                 # rootfs is now mounted read/write

$ passwd
Changing password for root
Password for root changed by root                  # password set to "root"

$ firstboot
firstboot has already been run
jffs2 partition is mounted, only resetting files

This should've been enough, but just for fun:

$ mtd -r erase rootfs_data
Unlocking rootfs_data ...
Erasing rootfs_data ...
Rebooting ...

And again, to overwrite the backing device:

> telnet
$ cat /dev/urandom > /foo                           # This is in fact /overlay/upper/foo
cat: writing 'foo': No space left on device

$ rm -f /foo
$ echo s > /proc/sysrq-trigger 
$ echo u > /proc/sysrq-trigger 
$ dmesg | tail
SysRq : Emergency Sync
Syncing device 1f:02 ... OK
Syncing device 1f:04 ... OK
SysRq : Emergency Remount R/O
Remounting device 1f:02 ... R/O
Remounting device 1f:04 ... OK

We can also install a fresh firmware image onto the system:

  • Download the correct squashfs-factory.img image.
  • Reset router and put it into failsafe mode:[24]
    • Power off the router
    • Press and hold the reset button
    • Power on the router and continue to press the reset button.
    • After a while, the router will respond to ping on
    • Release the reset button
  • Install via TFTP[25]:
$ echo -e "binary\nrexmt 1\ntimeout 60\ntrace\nput openwrt-XXX-squashfs-factory.img\n" | tftp
Packet tracing on.
sent DATA <block=6655, 512 bytes>
received ACK <block=6655>
Sent 3408005 bytes in 1.2 seconds

The router will automatically reboot into the new firmware.


The LEDE project and OpenWRT merged back together in January 2018.[26]