Linksys AC Series Router Configuration Tips for OpenWRT

Wiki.TerraBase.info
Revision as of 17:25, 22 April 2021 by Root (talk | contribs)
Jump to navigation Jump to search

This subject(s) of this article are the AC Series of routers manufactured by Linksys and the OpenWRT Firmware designed for them. The Linksys AC Routers include the WRT1200AC, WRT1900AC v1, WRT1900AC v2, WRT1900ACS v2, WR1900ACS v2, WRT3200ACM, and WRT32X. The WRT1900AC v2 is essentially a WRT1900ACS v1 and the WRT3200ACM and WRT32X are duplicate hardware models with different firmware (from Linksys) and the former blue / black and the latter black /gray. The models are sometimes referred to with out the suffix letters as WRT1200, WRT1900, WRT3200.

Information covered in this article was written for and tested on both the WRT1900ACS v1, WRT1900ACS v2, and WRT3200ACM. However the information applies to the other models as well.

All models are available on eBay and the ACS, ACM, and 32X series are available new as of the writing of this article in 2020. The most powerful and expensive models are the WRT3200ACM and the WRT32X. The best bargain used in terms of cost and "horsepower" is the ACS series. Occasionally it is possible to find a less than observant vendor on eBay selling an ACS model that is advertised as an AC model. Those are the best deals.

Details on each model are very nicely summarized on the OpenWRT website here: https://openwrt.org/toh/linksys/wrt_ac_series?s%5B%5D=wrt1200ac

As it started out, this article was intended to be a quick how to on a couple of items, but then grew to enormous proportions. There was some consideration on breaking it into smaller sections, but the Mediawiki interface with its table of contents mitigates that need to an acceptable level.

The information in this article comes from many sources and also from hard earned experience. It was collected in order to have a definitive repository of knowledge on the subject.

Quick S (as in Quick Start)

Because this article contains a lot of information in addition to "How to..." tutorials, this sections summarizes and provides links to the major "How to..." sections below.

  • Upgrade Firmware from Linksys to OpenWRT. The instructions on the OpenWRT website for upgrading from the stock Linksys firmware to OpenWRT are a bit behind the changes that Linksys is making with their GUI. What that means is one might have to hunt around a bit to find where Linksys has tucked away the firmware upgrade functionality.
  • Install several basic software packages that add very useful utilities. This includes software related to USB and eSATA storage device (Flash Drive, HDD enclosures, and even mSATA and M.2 NGFF & NVMe SSDs in USB 3.0 enclosures) and backup software. A suggested strategy is to install a bunch of basic utilities that can be used to recover from any issues related to an external USB Flash drive.
    • And now a quick side note that you'll read about in more detail later in this article. OpenWRT makes it possible to install a big chunk of the "operating system" (OS) for a router on a USB 3.0 Flash Drive. The partition volume it is mounted as is referred to as an "overlay" (again, more on this later). In a simple definition for this instance, which glosses over a lot of details, an overlay partition in OpenWRT can be equated to a spanned disk drive / volume. Essentially the internal Flash Drive and an additional USB 3.0 Flash Drive are combined / "concated" (sort of). In this simplistic comparison, the BIOS portion of a computer is equated to the internal Flash Drive and the disk drive is equated to the external USB Flash Drive. An overlay allows for a much larger "disk drive" to be used instead of relying on and being limited to the internal USB Flash Drive (although the same overlay technology is used to mount the internal Flash Drive if no external drive is available). Think of it like this, the basic Windows (or Linux) OS is installed on the Internal Flash Drive. It includes all of the basics to get things up and running. Then additional stuff is installed on the external USB 3.0 Flash Drive. The internal Flash Drive can still function, even if the external USB 3.0 Flash Drive is removed, albiet with reduced functionality (probably). It becomes advantageous in recovery / disaster scenarios to install as many utilities as possible on the internal Flash Drive that are focused on recovering a malfunctioning external USB 3.0 Flash Drive. Below are the recommended utilities to install. Note, they will also have to be installed on the overlay partition / volume once that is configured (again, it's covered later in this article).
    • Run the below commands to install the following items (but first, run opkg update). They're broken down into groups;
      • General Utilities: opkg install wget htop nano coreutils-dd netcat restic shadow-passwd shadow-useradd shadow-groupadd shadow-chsh lsof bash
      • Disk Related: opkg install block-mount e2fsprogs kmod-fs-ext4 kmod-usb-storage kmod-usb2 kmod-usb3 ntfs-3g usbutils gdisk cfdisk tune2fs kmod-fs-exfat dosfstools kmod-fs-vfat f2fs-tools kmod-fs-f2fs lsblk ntfs-3g-utils fdisk sfdisk wipefs hdparm
      • GUI Interface / Tools for "built-in" services: opkg install luci-app-advanced-reboot luci-app-uhttpd
      • Ease of Use Software: opkg install samba4-server samba4-utils luci-app-samba4 (of all the utilities to install, this is by far the largest in terms of storage space consumed)
      • Optional (if there's space or a need): opkg install mwan3 luci-app-mwan3 kmod-macvlan
      • Other Items to consider: "Packages that begins with coreutils", "Packages that begins with coreutils", "Other LuCI GUI Packages"
  • Partition and Configure OpenWRT to use external storage drives, not just for storage, but also as a replacement / addition to the internal non-volitile storage

Hardware

WRT1900AC

There are two hardware versions of the WRT1900AC, the v1 (version 1) and v2 (version 2). "v1" does not appear on the label, but is instead commonly used to differentiate between the original WRT1900AC and the version 2 model. Make sure to check the label on the bottom of the router and get the correct firmware.

WRT1900ACS

There are two versions of the WRT1900ACS. As with the WRT1900AC, the term "v1" is only used to differentiate with the version 2 model and does not appear on the model sticker. Unlike the WRT1900AC, both versions of the ACS router use the same firmware.

WRT3200ACM

As of the writing of this article on 7.2020, there is only one hardware version of the WRT3200ACM. The same is true for the WRT32X.

Storage (AKA Disk Drive) and File System

Another subject that OpenWRT is a bit opaque about is how information is stored on a router. It's not really their job, so let's go over it here.

A router is essentially a computer. It has all of the components of a computer, CPU, RAM, Network Adapter, Storage, etc. Unlike a computer, in a classic sense a router does not have a Disk Drive (unless one is attached via a USB or eSATA port), but it does have a way to store information which is Flash Memory. IE Flash Memory equals a Disk Drive (mechanical). In a more modern sense, it does have a disk drive in that modern disk drives in computers are SSD (Solid State Drives), which use a type of Flash Memory.

How OpenWRT handles that "Disk Drive" is much different than computers. Their explanation is here: https://openwrt.org/docs/techref/filesystems#squashfs

The part that OpenWRT doesn't explain very well is their "Overlay". Their Overlay is an abstraction layer that exposes a single interface to a user which is very similar to how a computer would present storage space to a user. On the other side is the Flash Memory which is broken down into two sections, firmware (equivalent to an Operating System) and storage space (equivalent to storage space on a disk drive or SSD for a computer). The firmware section is controlled by SquashFS and the storage space is controlled by JFFS/JFFS2

UBI = Unsorted Block Image, as in UBIFS (Unsorted Block Image File System)

Ethernet Switch

The Ethernet Switch typically transfers data at a sustained 90 MB/S for a Gigabyte Network Adapter.

Firmware

REMEMBER: The AC Series of routers has dual boot partitions, so if you're installing firmware it will flash it to the non-active flash partition. The same occurs if upgrading existing OpenWRT firmware. So if one happens to be running OpenWRT on one partition and DD-WRT or the stock Linksys firmware on the other partition, if installing from the OpenWRT / LUCI GUI, it will overwrite the other partition.

Dual Booting

This allows for rebooting to the alternate partition;

  • opkg update
  • Advanced Boot: opkg install luci-app-advanced-reboot

Log out and log back in to see the new LuCI feature (System, Advanced Reboot) OR Refresh browser windows (in Firefox Shift+RefreshButton)

Switching Boot Partitions

Commands for OpenWRT

  • To determine which boot partition is active: /usr/sbin/fw_printenv -n boot_part
  • To change which boot partition is active: /usr/sbin/fw_setenv boot_part 1 OR /usr/sbin/fw_setenv boot_part 2

Commands for DD-WRT

  • To determine which boot partition is active:ubootenv get boot_part
  • To change which boot partition is active: ubootenv set boot_part 1

Power Switch

Per this site: https://community.linksys.com/t5/Wireless-Routers/WRT1900AC-May-have-bricked-it/td-p/811096

  • Reset the router by holding the reset button in until the PWR light starts to flash, appx. 15 seconds.
  • Once the power light stops flashing, you can power off the router with the power switch.
  • Turn the power back on and the PWR light will light. As soon as any other light turns on, power off the router with the power switch.
  • Turn the power back on and the PWR light will light. As soon as any other light turns on, power off the router with the power switch.
  • Turn the power back on and the PWR light will light. As soon as any other light turns on, power off the router with the power switch.
  • Turn the power back on and the PWR light will light. This time just let the router power all the way up. It should now be on the alternate

Per this site: https://forum.archive.openwrt.org/viewtopic.php?id=70202

  • Start with the power switch off, then switch on. Watch the power LED:
  • Power LED: on (a few seconds)
  • Power LED: off (a second or two)
  • Power LED: on (immediately when the power light turns on, flip the power switch off)
  • That is 1 cycle of the 3 required to revert to the other partition. Repeat the above procedure two more times, making sure to flip the switch off as soon as the power LED comes on the second time.
  • The fourth time you turn the power switch on you can let the device boot and it should boot into the other partition.

After some experimentation, 4-5 seconds seems to be the sweet spot.

Here's what's happening "behind the scenes" when the the power switch is cycled in the above fashion. The observations were made with a TTL / Serial / USB cable attached to the header on a router board.

  • The Marvell firmware starts the boot process (equivalent to the BIOS of a PC)
  • There is a 2-3 second pause where one can press a key on the command console to instruct the router to boot into a very basic environment for loading firmware (sort of equivalent to a BIOS setup utility on a PC)
  • Before the 2-3 second window described above expires (and the boot process continues) is when the power button is turned off.

Below are a few of lines of information displayed during the boot process;

---below is the boot information after the "3nd power cycle"

BootROM - 1.73
Booting from NAND flash

General initialization - Version: 1.0.0
Detected Device ID 6820
High speed PHY - Version: 2.0

Init RD NAS topology Serdes Lane 3 is USB3
Serdes Lane 4 is SGMII
board SerDes lanes topology details:
 | Lane #  | Speed |  Type       |
 --------------------------------
 |   0    |  06   |  SATA0      |
 |   1    |  05   |  PCIe0      |
 |   2    |  06   |  SATA1      |
 |   3    |  05   |  USB3 HOST1 |
 |   4    |  05   |  PCIe1      |
 |   5    |  00   |  SGMII2     |
 --------------------------------
:** Link is Gen1, check the EP capability 
PCIe, Idx 0: Link upgraded to Gen2 based on client cpabilities 
:** Link is Gen1, check the EP capability 
PCIe, Idx 1: remains Gen1
High speed PHY - Ended Successfully
DDR3 Training Sequence - Ver TIP-1.26.0
mvSysEnvGetTopologyUpdateInfo: TWSI Read failed
DDR3 Training Sequence - Switching XBAR Window to FastPath Window 
DDR3 Training Sequence - Ended Successfully
Not detected suspend to RAM indication
BootROM: Image checksum verification PASSED
__   __                      _ _
|  \/  | __ _ _ ____   _____| | |
| |\/| |/ _` | '__\ \ / / _ \ | |
| |  | | (_| | |   \ V /  __/ | |
|_|  |_|\__,_|_|    \_/ \___|_|_|
         _   _     ____              _
        | | | |   | __ )  ___   ___ | |_ 
        | | | |___|  _ \ / _ \ / _ \| __| 
        | |_| |___| |_) | (_) | (_) | |_ 
         \___/    |____/ \___/ \___/ \__| 
 ** LOADER **


U-Boot 2013.01 (Mar 27 2015 - 16:50:46) Marvell version: 2014_T3.0p6

Boot version : v1.0.13

Board: RD-NAS-88F6820-DDR3
SoC:   MV88F6820 Rev A0
       running 2 CPUs
CPU:   ARM Cortex A9 MPCore (Rev 1) LE
       CPU 0
       CPU    @ 1600 [MHz]
       L2     @ 800 [MHz]
       TClock @ 200 [MHz]
       DDR    @ 800 [MHz]
       DDR 32 Bit Width, FastPath Memory Access, DLB Enabled, ECC Disabled
DRAM:  512 MiB

Map:   Code:                    0x1fea9000:0x1ff7632c
       BSS:                     0x1ffef6b4
       Stack:                   0x1f9a8f20
       Heap:                    0x1f9a9000:0x1fea9000
raise: Signal # 8 caught
U-ENV offset == 0x200000
raise: Signal # 8 caught
U-ENV offset == 0x200000
       U-Boot Environment:      0x00200000:0x00220000 (NAND)

NAND:  128 MiB
MMC:   mv_sdh: 0
DEVINFO offset == 0x900000
U-ENV offset == 0x200000
U-ENV offset == 0x200000
S-ENV offset == 0x240000


#### auto_recovery ####
[u_env] get auto_recovery == yes
[u_env] get auto_recovery == yes
[u_env] get boot_part == 1
[u_env] get boot_part_ready == 3
auto_recovery enabled:1, boot_part:1, boot_part_ready:3 

S-ENV offset == 0x240000
[boot_count_read] block:0x240000, size:128KB, records:64 
[boot_count_read_record] boot_count:2, next_record:53

[boot_count_write] erase:0, auto_recovery->block_offset:0x240000 offset=0x25A800

Updating boot_count ... 
[boot_count_write] offset:0x25A800 , length:2048
done

PCI-e 0 (IF 0 - bus 0) Root Complex Interface, Detected Link X1, GEN 2.0
PCI-e 1 (IF 1 - bus 1) Root Complex Interface, Detected Link X1, GEN 1.1
USB2.0 0: Host Mode
USB3.0 1: Host Mode
USB3.0 0: Host Mode
Board configuration detected:
mvEthE6171SwitchBasicInit init 
Net:   
|  port  | Interface | PHY address  |
|--------|-----------|--------------|
| egiga0 |   RGMII   |     0x01     |
| egiga1 |   SGMII   |     0x00     |
egiga0 [PRIME], egiga1
auto_recovery_check changes bootcmd: run nandboot 
Hit any key to stop autoboot:  2  <-- This is the countdown timer that starts at 3

--- and below is what it changes to after the "3rd power cycle / 4th power on" (minus all of the lines similar to above that come before it)

#### auto_recovery:2 ####
auto_recovery_check changes bootcmd: run altnandboot 
Hit any key to stop autoboot:  0

Upgrading the "Other Partition" from OpenWRT (be it another OpenWRT installation, Linksys firmware, DD-WRT, etc.)

As of 9.20.2020 much of the below is in question. It has been determined that when using the LuCI GUI and an upgrade firmware image (not Linksys Factory to OpenWRT) that the CURRENT partition (not the other partition) will be upgraded... Sometimes... ...but not always. The pattern seems to be very erratic. This is not good. Linksys Factory to OpenWRT seems to reliably flash the other partition. None of this is noted in the OpenWRT documentation.

Additionally, if flashing DD-WRT (there's a reason) to the other partition, per this site: https://forum.dd-wrt.com/phpBB2/viewtopic.php?t=318917&sid=ead6f3133aa640d078354c986b7c3981 and experimenting, it just does not seem possible to flash any recent version of DD-WRT to the other partition that works and doesn't create a "kernel panic" when booting. The solution?

  • From an OpenWRT partition, flash the other partition with OpenWRT
  • Get an old firmware version of DD-WRT (Linksys Factory to DD-WRT), version 37xxx or below, sometime in 2018, and flash that
  • The router won't reboot properly, but give it a minute or so to make sure the image is copied, then turn the router off, then on. It will then boot to DD-WRT
  • Note, if using Firefox or any other browser to access the DD-WRT GUI, it will probably keep redirecting to the LuCI GUI. Clear the browsing history or open a private tab in Firefox to solve that issue.
  • Get a more recent version of DD-WRT (upgrade version), flash that, good to go with OpenWRT on one partition and DD-WRT on the other.

OK, why DD-WRT? Well, as it turns out, DD-WRT has a bunch of development tools that OpenWRT does not. That means it is much, much easier to compile one's own sofware (packages, not firmware) on a router. This includes perl packages, etc. And, as tested, the binary / executables on DD-WRT are completely functional on OpenWRT as long as all the dependencies are in place. It is even possible to have a huge chunk of DD-WRT software in the /opt Directory available on OpenWRT. The easiest way to not run into conflicts is to only install software that is not available in OpenWRT in the /opt Directory. That way environment paths can be set up to search /opt first, then the normal OpenWRT binary / executables.

One thing to keep in mind about OpenWRT VS DD-WRT is how each refers to the CPU / SoC of the Marvell based hardware. OpenWRT refers to it as a Cortex A9. And it is. DD-WRT refers to it as ARMv7 and it is. Technically (see above section for details on the hardware). It's the same thing with both firmwares making a partial reference to the hardware's name. Arm, DD-WRT, and OpenWRT can all share the blame on this. See the chart on Wikipedia for some clarity: https://en.wikipedia.org/wiki/List_of_ARM_microarchitectures

Using LuCI to upgrade firmware, as of about 19.07.3, the upgrade process in the GUI has changed slightly and states: "Upload a sysupgrade-compatible image here to replace the running firmware." That might lead one to believe that the "running firmware", IE the currently booted and running version of OpenWRT will be upgraded. That is NOT the case. The LuCI GUI upgrade will upgrade the firmware on the other partition and then boot from the other partition. The OpenWRT message is probably related to the fact most routers do not have the special dual boot flash partitions that the AC Series has.

Using the command line to upgrade the firmware will upgrade the other partition, the subsequent boot will be to the current partition (IE, the one it was flashed from): sysupgrade -n -v -F /tmp/factory-to-ddwrt.bin (-n = do NOT keep current settings, -v = verbose, -F = Force)

So how does one upgrade OpenWRT firmware on the current / active boot partition when the process upgrades the other inactive partition? What about changing the boot partition to the inactive one and then upgrade the firmware (See the Switching Boot Partitions section of this article for the commands to view or change the boot partition)? After several attempts, this trick didn't work. Documentation exists that says this trick works with DD-WRT (https://forum.dd-wrt.com/phpBB2/viewtopic.php?t=311117). It seems the flashing of the NVRAM is left up to the Marvell SoS / CPU and there is no way around it via OpenWRT. Alternative?

The solution is to upgrade from the other partition. IE, if Partition 1 needs to be upgraded, boot to Partition 2 and perform an upgrade, which will then upgrade Partition 1. This will obviously work if OpenWRT is installed on both partitions. But how can one install DD-WRT on the other partition from OpenWRT?

Solution: Use the command line. IE, it won't work from the OpenWRT LUCI GUI.

  • Download the DD-WRT Factory Firmware (factory-to-ddwrt.bin) to the /tmp Directory
    • For WGET to work, this may be needed: opkg install libustream-mbedtls
  • Type the following command: sysupgrade -n -v -F /tmp/factory-to-ddwrt.bin (-n = do NOT keep current settings, -v = verbose, -F = Force)

The firmware will be installed on the other partition.

Remember: When attempting to utilize this within the LUCI GUI (if already logged in and connected), refresh the browser windows (CTRL Key plus Refresh Button in Firefox).

Only Upgrade versions of OpenWRT can be flashed via the GUI, not factory (unless the other partition is LinkSys firmware).

Use the OpenWRT Install / Factory image in this instance.

OpenWRT System Logging

In /etc/config/system, add the following lines;

  • option log_file '/var/log/messages'
  • option log_remote '0'

For additional information see: https://openwrt.org/docs/guide-user/base-system/log.essentials and https://openwrt.org/docs/guide-user/base-system/system_configuration

Storage: Internal NAND Flash Memory, USB Flash Drives, and eSATA Drives

Believe it or not, the stock installation of OpenWRT does not come with the capability to access USB or eSATA devices. Considering how prevalent a USB port is on routers these days, that's a bit baffling. Plus it's really frustrating for so many web sites that refer to the LuCI, System, Mount Point menu that doesn't exist unless the previously mentioned items are installed. Big woof on this one considering most newer routers have USB and / or eSATA ports.

Recommended Hardware Devices

The best recommendation for a USB Flash Drive is the SanDisk Ultra Fit USB 3.1 Flash Drive Series. And the recommendation is NOT because it is the fastest. They brag speeds up to 130 MB/S. Maybe downhill in a tornado, but under normal systems, that speed is a joke for this piece of hardware. So why recommend it? Well as it turns out, the fastest drive, USB, eSATA, or otherwise that has been tested on the AC Series is about 70 MB/S (this has been confirmed for eSATA) and around 45 MB/S for USB 3.0 (using a Patriot SuperSonic Rage Elite USB 3.1 Flash Drive that has been verified multiple times at over 200 MB/S sustained). Based on that and the below reviews it seems the Ethernet Switch may be topping out at about 70 MB/S, which is quite respectable.

Sabrent USB 3.0 Hub (HB-R3MB)
Sabrent USB 3.0 Hub

Some reviews have the USB 3.0 speeds and eSATA speeds about the same at around 70 MB/S: https://www.eteknix.com/linksys-wrt3200acm-router-review/10/

Others have the USB 3.0 speeds measured considerably slower at about 20 MB/S: https://www.kitguru.net/peripherals/james-morris/linksys-wrt3200acm-ac3200-wireless-router-review/4/

Anyway, the above mentioned SanDisk device tops out at about 70 MB/S on every system that the above mentioned Patriot device tops out at over 200 MB/S. Notice that 70 MB/S speed mentioned twice? Once for the SanDisk device and once for the AC Series. The next item to consider is price. The SanDisk is not the cheapest, but it is fairly low. When price and performance are both considered, it turns out the SanDisk device beats everyone. And since the AC series router and SanDisk USB Flash Drive both top out at around 70 MB/S, that makes it the perfect match.

If one is considering using the USB Flash Drive for other purposes, go with the Patriot USB Flash Drive. If using the USB flash drive as a dedicated device for an AC series routers then go with the SanDisk USB flash drive. Plus it's also much smaller and has a lower profile than the patriot device. Both drives claim speeds about double what they can deliver. The final joke is that the Patriot device is USB 3.0 and the SanDisk is a USB 3.1 device.

USB 3.0 Extension
USB 3.0 Extension

Another nice item, which isn't necessary, but makes nice neat way to connect several USB flash drives to a router is a Sabrent USB 3.0 Hub (model HB-RBM3). From Wal-Mart, only about $12. There are other similar device, but this one is much higher quality. Sadly, even with its ability to rotate, it won't plug into the router without blocking several of the Ethernet ports (including the WAN port) or the power connector. Thanks to the overhang on the rear of the AC Series router, it can't be rotated up. This is not the fault of the Sabrent USB 3.0 Hub, but the design of the Linksys Router that causes the issue. It is also worth pointing out that in tests, there was no drop in transfer speeds between a single USB Flash Drive plugged directly into the router's USB 3.0 port and the same drive plugged into the router via the Sabrent USB 3.0 hub.

USB to mSATA
USB to mSATA Enclosure


But there is a solution... A USB 3.0 A Male to A Female Adapter (Part # 1206-N, UPC 848076012233) from a company named CMPLE. It is available from several places: Wal-Mart, eBAy, and from the company that appears to have it manufactured (in China), CMPLE. Even at about $3.00 it is a bit more expensive than other similar products (and there are only a few). But it has one advantage in that the orientation of the male and female part of the connector are arranged such that the above noted 3 Port USB 3.0 hub from Sabrent can connect and be in the "up" position. All other similar items found require that the hub be rotated to the left, right, or down. Down isn't a choice unless one's router is on the edge of a table. Left and right are good as the adapter provides enough clearance for the hub so it doesn't contact the power cord or the Ethernet cable on the WAN port.

90 Degee Cable
90 Degee Cable

And did locate a cable that has chance (didn't test it by buying it) of fitting behind the above 90° USB 3.0 Hub noted above. The cable would also then have to bend at quite an angle to clear what ever the router was mounted on or sitting on. But it seems possible. It's from this company: http://www.wire-cable-solution.com/showing_2395_2071/ESATA-7Pin-small-90-to-SATA-First-generation.html

Watch out for other idiot sellers that list an "eSATA" cable that isn't. Look closely and you'll see that it's an internal SATA connector. The best tip when searching is to switch to Google or Bing images to find the proper cable.

Google also gives some false hope when searching for a cable like this when it shows just the item, but the link is dead or is redirected to generica SATA cables.


Bottom Line

Use an mSATA SSD in a USB 3.0 enclosure.

A quick test using the DD utility to copy a "Zero Byte" file to various devices (Flash Drive, mSATA SSD, etc.) resulted in the following speeds;

...not even close. An mSATA SSD in the above enclosure blew everything else out of the water. And it was just an average mSATA SSD (https://www.newegg.com/vaseky-v800-128gb/p/0D9-00D6-00008?Item=9SIAGKC7VJ8289). Together, maybe a bit more expensive than a similar sized good Flash Drive, but as DeadPool said, "...worth it!"

Overlay

Before getting into the "how" with an external storage device, it is worth pointing out one of the more useful features available in OpenWRT.

Whatever external storage device is chosen, be it an old USB 2.0 Flash Drive that's been sitting in a drawer to an 8 TB or more HDD in an eSATA enclosure, it can be used in the capacity of just a storage device. However, there is a nice feature that allows for additional software that acts in conjunction with the basic firmware of the router to be stored on an external storage device. To put it in terms of a computer, the router can be a computer that has two storage devices. One for the Operating System (Firmware in the case of a router) and the other for file storage. But what if the Operating System (AKA firmware) could also reside on an external storage device. With OpenWRT it can.

There are two choice to make in regards to relocating the OS of a router. The first choice, referred to as "Overlay", has part of the OS continuing to reside on the internal Flash Storage with the rest on an external storage device. The second choice, mounting the external storage device as the "root filesystem" can move almost all of the OS to the external storage device.

Details on the OpenWRT booting process, overlay, file systems, etc. can be read about at the below links. Don't do any of it yet, just read it for the technical background information;

Both choice offer almost unlimited expansion of the OS, limited only by the size of the storage device(s) connected, with neither offering a performance advantage over the other. The "Overlay" choice is the safer of the two if the external storage device malfunctions. If a malfunction does occur, the router will essentially revert to a "newly flashed" state. This allows for a new external flash drive to be connected and hopefully a backup restoration. The second choice is more dangerous in that any malfunction of the external storage device will result in the router being unresponsive to normal access methods.

Even with the huge (compared to other routers) amount of non-volatile Flash Storage space available on the AC Series of routers, sometimes it isn't enough. There's a total of 128 MB for the AC and ACS, and a whopping (relative to routers) 256 MB available on the WRT3200ACM. But... There's always a "but". Even with the ACM, typically only a single 80 MB partition is readily available. And of that, only about 70 MB is available as free space (half that for the AC and ACS series).

It is possible to access all of the internal Flash Storage space, as described below. But be careful when using it as it could make the router malfunction, be overwritten, etc. The available Flash Memory Storage could certainly have been utilized more efficiently. And don't blame OpenWRT for that. It is Linksys that designed the Flash Memory Storage design into the hardware.

Anyway, there is a nice solution to overcome the storage limitations of the router using a feature called "Overlay". In short, a USB Flash Drive or eSATA drive or mSATA drive (in a USB 3.0 enclosure) can be used instead.

REMEMBER: If using Overlay with a USB device, if the system is rebooted, when viewed in the LuCI GUI interface the "Enable Mount" will not be checked for the device that is mounted as an Overlay device, but it will be mounted. It can be checked and mounted for access at an additional /mnt point with no ill effects.

Software Needed for USB Flash Drives to Connect, Partition, Format, etc., with Other Configuration Tools and the LuCI GUI Interface

  • opkg update
  • opkg install block-mount e2fsprogs kmod-fs-ext4 kmod-usb-storage kmod-usb2 kmod-usb3 ntfs-3g usbutils gdisk cfdisk tune2fs kmod-fs-exfat dosfstools kmod-fs-vfat f2fs-tools kmod-fs-f2fs lsblk ntfs-3g-utils fdisk sfdisk wipefs blkidmkfs hdparm (block-mount is the package that enables the "Mount Points" menu to appear in the LuCI GUI interface, and a reboot is necessary after installation)

Please note, all of the above packages are not necessary. But they do represent a broad range of tools that are very useful. And since they don't take up a lot of space, it's worth installing them. They don't run as active services or anything either, so no extra RAM or CPU usage unless one types the command. Reboot after installing all of the above software.

The above installed sofware provides many new commmands for "disk drives" (Flash Drive, SSD, HDD, etc.), including;

  • e2fsprogs: mkfs.ext2, mkfs.ext3, mkfs.ext4, etc.
  • kmod-fs-ext4: Includes ext2, ext3, and ext4
  • tune2fs: Changes a volume label
  • block-mount: Displays a volume label
  • df: Displays general partition information
  • cfdisk: A text GUI equivalent for gdisk or fdisk
  • lsblk: Shows the type of formatting
  • parted: A Linux utility that does not seem to be available with OpenWRT

Configuration with LuCI GUI Interface is located here: System, Mount Points

Partition Table, Partitioning, Formatting, and Performance Tuning a USB Flash Drive

A recommended method with the AC Series of routers is to create two EXT4 Partitions (one for each boot partition), an NTFS Partition (for compatibility with Windows), and a SWAP Partition. Also remember there is a difference between the MBR and GPT numbering of Partition types (IE, Linux Swap in MBR is 82 and 19 in GPT).

To switch from GPT to MBR without losing existing partitions, see this web site: https://sites.google.com/site/aleksanderbrain/ubuntu-server/disk-management/convert-from-gpt-to-mbr-partition-table

For a USB Flash Drive or eSATA drive on a router, MBR is absolutely fine. Several programs such as CGDISK (not CFDISK), GDISK, etc., insist on creating a GPT disk without giving the end user a choice. They demand it be done their way. If one is comfortable with being pushed around and forced to do something like that, fine. If not, choose a utility like CFDISK. Is a GPT partitioned drive better? Well, define better. It is newer, has more options, etc., but guess what? It's still a router with a Flash Drive or eSATA drive and MBR is fine. Is GDISK a better program? Well, it is way more powerful and has far more capabilities than CFDISK, so in that respect, yes. But in respect to giving the end user the final choice in what is done? Not so much.

Utilities to Display Information about Drives / Disks

  • df (Displays information about mounted file systems)
  • block info (Displays additional information about mounted file systems)
  • lsblk -l (Displays information about ALL available Drives / Disks)
    • The items shown as "mtdblockX" are different the different "partitions" for the routers internal Flash Drive (equivalent to a computer's disk drive, OpenWRT refers to it as NAND (Not AND) Flash Memory). These partitions are dictated by the hardware as Linksys designed and layed it out.
    • Anything starting with sd (sda, sdb, sdc, etc.) are the USB or eSATA devices connected to the router.
  • blkid (Similar to block info and lsblk)

Partition Table

For small USB 3.0 Flash Drives, use the MBR Partition Table. The following command will start things off with a clean slate. There are instances where a Flash Drive may have been previously configure to use a GPT Partition Table which can cause issues with GDISK and other partitioning Software;

  • wipefs -a /dev/sdX (If it isn't installed, use this command: opkg install wipefs

When starting CFDISK, if prompted to "Select label type", it means the Flash Drive or SSD has been initilized back to its most basic state. Choose DOS, which equates to MBR.

Partitioning

CFDISK is one of the easier utilities to use because of its "text GUI" style interface. I also aligns partitions on solid state devices correctly, as does most modern partitioning software. Don't forget to set the partition type too (7=NTFS, 83=Linux, 82=Linux Swap, etc.). The interface is fairly self explanatory, but in order to commit changes remember to select Write and confirm by typing "yes";

  • cfdisk /dev/sdX (Example cfdisk /dev/sda)

If the Partition Table does not exist, CFDISK will prompt for one to be selected. Choose DOS, which equates to MBR in "Linux Speak". One oddity after partitioning with CFDISK is that if the same device is viewed in GDISK, that program will complain that a partition table overlaps another one. This is not an issue with the partitioning at all. This is the GDISK program whining that it wasn't left space at the end of the SSD to create room to make the drive a GPT, and then trick other software and computers into thinking it is an MBR disk. That's deceptive and misleading. Use CFDISK, make an MBR based drive, good to go. Done.

To check proper partition alignment (if it starts on a boundary divisible by 1024, then it is properly aligned, newer partition software generally does this properly for flash based devices);

  • sfdisk -d /dev/sdX
  • fdisk -l -u /dev/sdX

Formatting

Formatting an EXT4 Partition (remember to unmount before formatting if a drive is being used);

  • mkfs.ext4 -L WhatEverName -v /dev/sdaX (-L = Label, -v = Verbose)

Format an NTFS Partition;

  • mkntfs -f -L NTFS -v /dev/sdaX

Change a Volume Label;

  • tune2fs -L WhatEverName /dev/sdaX

Performance Tuning for ExtX

The below commands can be used to enhance performance for the ExtX File Systems, but are negligable according to this site: https://cromwell-intl.com/open-source/performance-tuning/file-systems.html

  • tune2fs -o journal_data_writeback /dev/sdaX
  • tune2fs -O ^has_journal /dev/sdaX

Performance Tuning for NTFS

For NTFS volumes enabling "big_writes" makes a HUGE difference in performance. Some Linux systems claim this setting is deprecated, but for OpenWRT it works and makes a big performance difference. Real world file copy performance was measured at sustained 60 MB/S for a USB 3.0 Flash Drive and almost 90 MB/S for an eSATA HDD.

  • In the LUCI GUI, Mount Points, Mount Points, Edit, Advanced Settings, Mount Options add: big_writes
  • If compression is also desired, add this in the above noted location: big_writes,compression

Clone a Partition

It is recommended to make sure the destination partition is the same size or larger of course. Be prepared to wait a while, even on a USB 3.0 port.

  • dd if=/dev/sda1 of=/dev/sda2 status=progress (to take advantage of the "status=progress" feature, the full version of dd must be installed: opkg install coreutils-dd)

Note: After cloning, to save confusion and sanity, remove the source drive. It also may be necessary to reboot the router or dismount and mount the drive if it was already mounted to see the "cloned" directories and files. All of this is necessary because everything is cloned and OpenWRT may display two /dev/sdX devices that are exactly the same (IE sdb1 and sdb1 as two distinct, but duplicate device partitions). Also remember that DD is not a sophisticated cloning utility, so when cloning an entire partition, it will clone the entire partition, including empty / blank space. Acronis, Clonezilla, etc. will ignore empty space by default (the option exists to do a "sector by sector" copy which includes blank space), thus speeding up the cloning process.

Use an External Drive (USB Flash Drive, USB to mSATA) instead of internal Flash Memory using Overlay

In the LuCI GUI interface;

  • System, Mount Points, Mount Points, Add, General Settings (select the USB Flash Drive Partition)
    • Add by one of several methods, UUID displays device too (IE, /dev/sda1)*
    • Use as external overlay (/overlay)
  • ...Advanced Settings
    • File System: EXT4, NTFS, etc.
    • Mount Options
      • EXT4: barrier=0,data=writeback
      • NTFS: big_writes,compression

* Linux systems do not reliably discover sdX devices in the same order. So on an AC Router with multiple devices attached (IE, a USB 3.0 and eSata device OR mulitple USB 3.0 devices attached with a hub) there is no reliable method to predict which device will be sda, sdb, sdc, etc. IE a device on the USB 3.0 could be sda and a device on the eSATA port could be sdb on one boot. The next one might have them switched with the USB 3.0 device as sdb and the eSATA device as sda. With that in mind, use the UUID number when mounting a device to have it consistently attached to the same mount point (IE, /mnt/sda1, /mnt/sdb1, etc.) See the below sites for more information;

Access and Use an External USB Flash Drive

Install the drivers and LuCI interface as noted above, then in the LuCI GUI Interface;

  • System, Mount Points, Mount Points, Add, General Settings (select the USB Flash Drive Partition)
    • Add by one of several methods, UUID displays device too (IE, /dev/sda1)
    • Mount Point (type it manually): /mnt/WhatEverName (Match it to the device name, IE /dev/sda1 will be mounted as /mnt/sda1)
  • ...Advanced Settings
    • File System: EXT4, NTFS, etc.
    • Mount Options
      • EXT4: barrier=0,data=writeback
      • NTFS: big_writes,compression

REMEMBER;

  • If using a the USB 3.0 by itself (IE, nothing plugged into the eSATA / USB 2.0 port), the flash drive will be referred to as device SDA (with partitions SDA1, SDA2, etc.)
  • If the eSATA port / USB 2.0 port is used by itself, the same naming convention applies.
  • If both ports are used, but only the USB 3.0 device is mounted it will still be referred to as SDA (etc.)
  • BUT, and this is a tricky thing
    • If both ports are used, but only the USB 3.0 device is mounted, as soon as an eSATA / USB 2.0 port device is mounted it will be seen as SDB (etc.)
    • BUT, big BUT here, when the system is rebooted, the eSATA / USB 2.0 device can sometimes be mounted first, so SDA and SDB are reversed. WOOF!

Swap Partition or Swap File

A Swap Partition or Swap File can be used.

Most references to Swap Partitions or Files indicate performance is quite poor. There is considerable ancient / old /archived information about Swap Files and OpenWRT. But this may have been written during the USB 2.0 period and doesn't reflect the performance of USB3 or eSATA devices in 2020. That said, "Virtual RAM" is slow. Is it slower than RAM? Yes. Does one sometimes need more RAM than is physically available? Yes, sometimes. So for all the people that discourage the use of a Swap File, fine. But sometimes one needs it. Unlike other routers, the AC Series comes with an astounding amount of RAM (512 MB), so it may not be an issue. But here's how to do it...

Make sure there is an available empty partition for usage of a Swap File, then;

  • mkswap -L SWAP /dev/sdaX
  • Use the LuCI GUI interface

OR

  • mkswap -L SWAP /dev/sdaX
  • swapon /dev/sdaX

It is recommended to use the GUI to be able to monitor it later. Check functionality with: HTOP

Inactive Internal Flash Memory Partitions and Linksys Reserved NVRAM / Flash Memory Partition Mounting and Information

Internal Flash Memory Partitions (mtd6 (rootfs1 UBI), mtd7 (rootfs2 UBI), and mtd9 (syscfg UBI), etc.) can also be mounted and accessed. For more information on the WRT3200ACM Flash Memory Layout, click here (other AC models are similar, but different sizes). Other mtdX Flash Memory sections can also probably be accessed, but are not addressed here.

One use for this would be to manually edit settings from the active partition to the inactive partition to fix some type of issue.

Viewing Available Internal Partitions and Information

NOTE: Most of the below information in this section is from the perspective of OpenWRT. DD-WRT has a slightly different "perspective" on the layout.

See https://openwrt.org/toh/linksys/linksys_wrt1900ac, https://openwrt.org/toh/linksys/linksys_wrt1900acs, and https://openwrt.org/toh/linksys/linksys_wrt3200acm for Flash Memory Layouts of each AC Router Model. The Flash Memory (non-volatile RAM / NVRAM) Layout is directly comparable to Partitions on a Personal Computer's disk drive or SSD.

Various commands to "see" the available internal Flash Memory partitions;

  • ls -la /dev/ub* : A directory listing of UBI devices
  • cat /proc/mtd : A list of the various MTD (Memory Technology Device) Partitions
  • UBI (Unsorted Block Images) Commands;
    • ubinfo - provides information about UBI devices and volumes found in the system
    • ubiattach - attaches MTD devices (which describe raw flash) with UBI which creates corresponding UBI devices;
    • ubidetach - detaches MTD devices from UBI devices (the opposite to what ubiattach does);
    • ubimkvol - creates UBI volumes on UBI devices;
    • ubirmvol - removes UBI volumes from UBI devices;
    • ubiblock - manages block interfaces for UBI volumes. See here for more information;
    • ubiupdatevol - updates UBI volumes; this tool uses the UBI volume update feature which leaves the volume in "corrupted" state if the update was interrupted; additionally, this tool may be used to wipe out UBI volumes;
    • ubicrc32 - calculates CRC-32 checksum of a file with the same initial seed as UBI would use;
    • ubinize - generates UBI images;
    • ubiformat - formats empty flash, erases flash and preserves erase counters, flashes UBI images to MTD devices;
    • mtdinfo - reports information about MTD devices found in the system (not available in OpenWRT)

How the internal non-volatile flash memory (equivalent to a disk drive in the router) is arranged (Note: The WRT1900ACS and WRT3200ACM have slightly different numbering noted below as WRT1900ACS Name and Number / WRT3200ACM Name and Number;

  • mtd5 / mtd6*** (the first bootable flash memory partition)
    • Referred to as ubi with cat /proc/mtd if it is the active partition or rootfs1 if it is the inactive partition
    • Referred to as: rootfs1 in OpenWRT Documentation
    • Referred to mtdblock5 / mtdblock6*** in the LuCI GUI UUID drop down menu
    • Referred to as ubi0 in /sys/devices/virtual/ubi, which in turn includes ubi0_0 (kernel* image) and ubi0_1 (usable flash storage)
  • mtd7 / mtd8*** (the second bootable flash memory partition)
    • Referred to as ubi with cat /proc/mtd if it is the active partition or rootfs2 if it is the inactive partition
    • Referred to as: rootfs2 in OpenWRT Documentation
    • Referred to mtdblock7 /mtdblock8*** in the LuCI GUI UUID drop down menu
    • Referred to as ubi2 in /sys/devices/virtual/ubi, which in turn includes ubi2_0 (kernel* image) and ubi2_1 (usable flash storage)
  • mtd8 / mtd9*** (a flash memory partition used as a temporary storage location when new images are temporarily stored during the flash process)
    • Referred to as syscfg with cat /proc/mtd and the OpenWRT Documentation
    • Referred to mtdblock8 / mtdblock9*** in the LuCI GUI UUID drop down menu
    • Referred to as ubi2 in /sys/devices/virtual/ubi, which in turn includes ubi1_0 and ubi1_1 (typically ubi1_0 is detached by default, ubi1_1 has to be attached manually)

The WRT3200ACM has an extra partition, mtd4, labeled as sysdiag.

By default, the attached UBI partitions attached are;

  • ubi0: mtd4 / mtd5***
  • ubi0_1: Kernal Image portion of mtd4 / mtd5*** OR mtd6 /mtd7***, depending on which is active
  • ubi0_1: Root FS portion of mtd4 /mtd5*** OR mtd6 /mtd7***, depending on which is active
  • ubi1: mtd8 / mtd9*** is the partition used as a temporary storage location when new images are temporarily stored during the flash process
  • ubi1_0: same as UBI1, but use ubi1_0 when mounting
  • ubiX, ubiX_0, ubiX_1, etc. are additional UBI Partitions that are attached with the ubiattach command

It does not appear that the Kernal Image portion of mtd4 / mtd5*** OR mtd6 / mtd7*** can be mounted (IE, /dev/ubiX_0, for example /dev/ubi0_0, /dev/ubi1_0, etc., cannot be mounted), unless it is the mtd8 / mtd9*** partition used as temporary storage when flashing an image to the router.

*** Remember: mtdX / mtdY refers to the minor difference between the 1900 series and 3200 series of AC Routers. IE the 1900 series router's mtd4 is mtd5 on the 3200 series.

The full memory layout can be found here;

Remember, the flash memory layout of the AC Series was created by Linksys, not Marvell. And as noted by some, it seems a bit wasteful in how it was utilized.

The below information illustrates the difference in "perspective" between OpenWRT and DD-WRT in terms of how each of them "sees" the underlying partitions. The below information was obtained from a router with OpenWRT on partition 1 and DD-WRT on partition 2. The naming of the first four partitions is similar. The naming difference on mtd4 - mtd7 is a difference in naming conventions between the two firmwares. But notice the last "2 or 3" partitions... DD-WRT makes use of the "unused" mtd8 (from OpenWRT perspective) and divides it into two partitions (mtd8 and mtd9), nvram and dd-wrt.

There is no explanation for the size differences.

---OpenWRT (cat /proc/mtd)

dev:    size   erasesize  name
mtd0: 00200000 00020000 "u-boot"
mtd1: 00040000 00020000 "u_env"
mtd2: 00040000 00020000 "s_env"
mtd3: 00100000 00020000 "devinfo"
mtd4: 02800000 00020000 "kernel1"
mtd5: 02200000 00020000 "ubi"
mtd6: 02800000 00020000 "kernel2"
mtd7: 02200000 00020000 "rootfs2"
mtd8: 02600000 00020000 "syscfg"
mtd9: 00680000 00020000 "unused_area"

--DDWRT (cat /proc/mtd)

dev:    size   erasesize  name
mtd0: 00200000 00020000 "u-boot"
mtd1: 00040000 00020000 "u_env"
mtd2: 00040000 00020000 "s_env"
mtd3: 00100000 00020000 "devinfo"
mtd4: 02800000 00020000 "linux"
mtd5: 02500000 00020000 "rootfs"
mtd6: 02700000 00020000 "linux2"
mtd7: 02400000 00020000 "ubi"
mtd8: 00040000 00020000 "nvram"
mtd9: 02500000 00020000 "ddwrt"
mtd10: 00680000 00020000 "unused_area"

Mounting Internal Partitions

To view information about available UBI devices and partitions;

  • ls -la /dev/ub* : A directory listing of UBI devices
  • cat /proc/mtd : A list of the various MTD (Memory Technology Device) Partitions

See http://www.linux-mtd.infradead.org/doc/ubi.html for additional information about UBI

The LuCI GUI cannot attach internal Flash Memory Partitions via the Mount Points MTDBLOCKx method, nor can the block mount /dev/ubiblockX command. Editing the /etc/config/fstab file is the only method that works (Note, not the /etc/fstab file) if the system is rebooted.

The below example of /etc/config/fstab file (which can be created manually or within the LuCI GUI) to mount the mt8 / rootfs2 partition does not work as OpenWRT will not mount it (The block mount command mounts the various items in the /etc/config/fstab file);

The below /etc/config/fstab Entry will NOT work;

config mount
        option device '/dev/ubi2_0'
        option target '/tmp/MTD8'
        option fstype 'squashfs'
        option enabled '1'

Instead, edit the /etc/rc.local file to to mount an the mtb8 / rootfs2 internal flash memory partition;

The following will mount the second flash memory partition (mtb8 / rootfs2) for a WRT3200ACM, adjust as noted above for the AC or ACS.  Also remember that if one of the mtd partitions is already attached an error will occur with the ubiattach command, so just go to the next command;

ubiattach -m 8
mkdir /mnt/mtd8
mount -t ubifs /dev/ubi2_1 /mnt/mtd8

The following will mount the mtb9 / syscfg partition (if it isn't already mounted)

ubiattach -m 9
mkdir /mnt/mtd9
mount -t ubifs /dev/ubi1_0 /mnt/mtd9

Another example for the WRT1900ACS model: What if the router is booting from the external USB flash drive and there is a need to switch back to booting from the internal flash drive (first partition)? Good luck trying that with the LuCI GUI (IE, it won't work). Solution? See below;

  • Attach and Mount the mtd5 / rootfs1 partition (see the "partition map" for the WRT1900ACS on the OpenWRT website)
ubiattach -m 8 (The odds are it is already attached.  If an error occurs, that indicates it is already attached)
mkdir /mnt/mtd5
mount -t ubifs /dev/ubi0_1 /mnt/mtd5 (ubi0_1 is the partition noted as "mtd5 rootfs1 (ubi)")

Just for information: ubi0 is the partition noted as kernel1 in the, ubi0_0 is the partition noted as "primary kernel image", neither of which can be mounted.

ubi0_0 and ubi0_1 will always be the current partition and ubi1_0 and ubi1_1 will be the inactive partition (assuming there are no USB flash drives attached)

Also keep in mind, as noted above, there is a minor difference between the partition layouts of the WRT1900AC/ACS and the WRT3200ACM routers.

  • Access the partition here: /mnt/mtd5/upper (the directory structure at this point is equivalent to how it would be seen when in use), then edit the /mnt/mtd5/upper/etc/config/fstab file and set the open enabled '1' to '0' for the option target "/overlay" partition.
  • Reboot and the router will boot from the internal flash drive, mtd5 partition.

Some Additional Commands to Attach Internal Partitions

  • To attach a UBI Partition: ubiattach -m 6 OR ubiattach -m 8 OR ubiattach -m 9 (an error will occur if a partition is already mounted)
  • To mount the second bootable partition;
    • mkdir /tmp/MTD8 (this follows the OpenWRT convention in terms of the location to mount it, instead of using the /mnt directory)
    • mount -t ubifs /dev/ubi2_1 /tmp/ubi2_1 (or MTDBLOCK8, etc)
  • An alternative method from here to mount the second bootable partition has a slightly different method which didn't seem to work quite right with the final command;
    • ubiattach -m 8
    • ubiblock --create /dev/ubi2_0
    • mount -t squashfs -o ro /dev/ubiblock2_0 mnt

To mount the syscfg partition (mtd9), if it isn't already mounted under /tmp/syscfg;

  • mkdir /tmp/MTD9 (this follows the OpenWRT convention in terms of the location to mount it, instead of using the /mnt directory)
  • mount -t ubifs /dev/ubi1_0 /tmp/MTD9

NOTE: The mounting of the mtb9 (syscfg UBI) for various models of the AC Series seems to be erratic, in that some automatically mount it and others don't. Even in ones where it is mounted, it isn't listed in the /etc/config/fstab file.

NOTE: The directory structure of the mtd8 / rootfs2 partition will not be the same as if it were the active partition. Look in the directory named "upper" for the /etc, /sbin, etc. directories.

WRT3200ACM UBI Layout

On a WRT3200ACM with both the mtd6 (rootfs1), mtd8 (rootfs2), and mtd9 (syscfg) partitions attached, ls -la /dev/ub* or cat /proc/mtd will show the following devices;

UBI Devices Attached

/dev/ubi0_0
/dev/ubi0_1
/dev/ubi1
/dev/ubi1_0
/dev/ubi2
/dev/ubi2_0
/dev/ubi2_1
/dev/ubi_ctrl
/dev/ubiblock0_0

ubi0_0: The read only kernel / firmware image for mtd6 (under mtd5)

ubi0_1 (mtd6 / rootfs1): The squashfs / ubifs read / write partition

ubi1_0 (mtd9 / syscfg): The flash memory partition used as a temporary storage location for new firmware

ubi2_0: The read only kernel / firmware image for mtd8 (under mtd7)

ubi2_1 (mtd8 / rootfs1): The squashfs / ubifs read / write partition

See the OpenWRT documentation for the memory layout of the WRT3200ACM here.

Additional Information

/sys/devices/virtual/ubi/ubi0/mtd_num is a file that indicates the current / active partition, which is 6 (for mtd6) or 8 (for mtd8)

/sys/devices/virtual/ubi/ubi1/mtd_num is the file that indicates the mtd9 / syscfg partition, which is 9

Performance Thoughts

Performance Testing

In order to determine "end user speed", the below rates were measured using Windows Explorer between an M.2 SSD on a Windows 2016 Server and the below routers using Samba 4 (FD = Flash Drive and HDD = Hard Disk Drive). CPU, Flash Drive, HDD, Gigabit Switch connecting devices, etc. were all tested on other systems at faster speeds, so they are not the limiting factor. IE, the below tests reliably measure the bus speeds of the router(s);

Router Model -->
MB/S Read - Write
Port Connected to
WRT1900ACS WRT3200ACM with Flash Drive WRT3200ACM with eSATA in USB Enclosure
eSATA HDD NTFS 60 - 85
USB 3 FD ext2 50 - 70 - 14
USB 3 FD ext3 40ish - 40ish
USB 3 FD ext4 50 - 50 33 - 20 90 - 50
USB 3 FD NTFS 30 - 70 30 - 24 90 - 50
exFAT Forget It Didn't try
FSFS same as ext2
FAT32 4 GB size limit

It is worth noting the above Read - Write speeds are not reversed. Counter to what is normally experienced, Read speeds are regularly slower than Write.

In other testing using an FTP (vsFTPD) daemon on the router and WinSCP with an mSATA SSD connected to the USB 3.0 port and a Windows computer with a drive configured as RAID 0 with dual M.2 Samsung 970 EVO SSDs (IE, that is not the limiting factor) the speeds were higher than noted above. The computer and router were connected with a Dell PowerConnect Switch using link aggregation on the computer side with two ethernet connections (again, not a limiting factor on the computer end). Link aggregation does not seem to be a possibility on a router such as the AC Series, as with most routers, because even though there is a physical switch, there is only a single ethernet adapter connected to the switch from the SoC (on the LAN side, 2 if the WAN is counted). So data coming through the switch which moves to the USB 3.0 or eSATA port has to "pass through" a single ethernet adapter, because that's all that exists for the SoC (System on a Chip) hardware in the AC Series routers. Anyway, sustained read / write transfers to EXT4 formatted partitions were measured at almost 110 MB/S. NTFS formatted partitions were slightly slower, approaching 90 MB / S. This is probably a peak speed for the router as limiting factor observed during the file transfer was CPU usage. A 1.866 GHz WRT3200ACM was using above 80% of CPU resources for vsFTPD and other service, so a 1900 series router would be approaching 100% CPU usage. Transfers to a mechanical HDD on the eSATA port were only a couple of percentage points slower for both EXT4 and NTFS partitions when compared to the above mSATA connected to the USB 3.0 port.

Compatibility and Recommendations

For compatibility with Windows choose NTFS (and accept the speed hit on OpenWRT).

For OpenWRT Native Overlay use EXT4.

F2FS supposedly has issues, even though OpenWRT recommends it, so do NOT use it.

vFAT or any FAT is a joke and either doesn't work, performs like a dog, or has space limitations.

Cloning a USB Flash Drive

Cloning an OpenWRT USB Flash Drive with Acronis

Don't do it. Acronis will successfully clone a USB flash drive, but there is no guarantee it will put the partitions back in the same order

Cloning an OpenWRT USB Flash Drive with EaseUS (or another equivalent utility)

It works, but... It is dog slow, even for partitions and file systems that contained no data, files, or directories. The process took almost half an hour with two identical USB 3.0 Flash Drives. No detailed logs were available, but the odds are it went sector by sector. So that means a completely full USB Flash Drive would take just as long to copy as one that was partitioned and formatted, but contained no data.

Alternative Cloning Methods

OpenWRT doesn't have much in the way of backup or cloning software. There is no cloning software. The one piece of backup software, RESTIC, is a very functional piece of software, but it doesn't facilitate backing up from USB Flash Drive to another. The lack of OpenWRT software for cloning and backing up is probably because most hardware devices do not have multiple USB Ports. Additionally, most routers are probably not configured to boot from a USB Flash Drive using the Overlay functionality in OpenWRT, IE, they just boot from their internal non-volatile Flash Memory.

Clonezilla is a viable alternative, but requires booting a computer from a "Live CD" as it is not a Windows program.

Networking and Related Services

The OpenWRT article on Basic Networking, Aliases, etc. includes a lot of information. But they don't explain in a simple manner, what is occuring in some instances. Below are a few examples;

  • BR Term: The "br" part of br-lan name (seen in the LuCI GUI or when using the ifconfig command) is automatically assigned to a network interface if it's type is set to "bridge". OpenWRT refers to this as a pseudo interface. IE, if an interface defined in the /etc/config/network file is option type 'bridge' then "br" with a hyphen ( br- ) is prepended to the name of the interface ( interface 'lan' ) in the /etc/config/network file
  • Firewall Tip: Make sure each new "Interface" is include in the firewall setting (LuCI GUI: Interface, Firewall Settings, Assign Firewall Zone OR File: /etc/config/firewall, config zone (lan), option network, add the name of the interface)
  • Syntax Item: OpenWRT examples tend to vacillate between one of two different syntax in their examples, for instance;
    • option 'type' 'bridge' OR option type 'bridge' (the latter seems to reflect how the actual configuration files are done)
  • Alias or Second IP Address Tip: The option ifname item in the Alias or Secondary IP Address Network Configuration should be set to the above mentioned br-lan ( or if the default name has been changed from lan to lan1, then br-lan1 ). Do NOT set it to the option ifname 'eth0.1' (default name) or lan if the type is set to bridge as some examples give and don't emphasize the "in this example the interface is not configured as a bridge" note. The br-lan interface name doesn't exist in the /etc/config/network file, but it is if the IFCONFIG command is typed it does show the br-lan interface, and in LuCI it shows both (/etc/config/network name in large letters at the top and the IFCONFIG command name smaller on the bottom). How is one supposed to know? Well, as mentioned in the BR Term bullet point above, this information was discovered after a bit of experimenting. Thus the initial comment about the OpenWRT documentation leaving out a key detail to actually making things function.

Notes;

  • Items in the above bullet points noted in italic represent configuration statements in a file.
  • Items below and above are referred to as Adapter(s) (NIC, Network Interface Card, etc.) and Interface(s) interchangabely, even though using the term Adapter is usually in reference to a piece of hardware and Interface usually refers to the Adapter as it is seen from an OS.

Default Network IDs, Labels, Configuration

WRT1900AS, WRT1900ASC, & WRT3200ACM IPv4
Port # (as labeled on back of router) Port # (from OpenWRT perspective) /etc/config/network Name ifconfig VLAN Assigned an IP Address
LAN 1 3 LAN br-lan (eth0.1 set to bridge mode) 1 Yes, and is assigned to br-lan
LAN 2 2 LAN br-lan (eth0.1 set to bridge mode) 1 Yes, and is assigned to br-lan
LAN 3 1 LAN br-lan (eth0.1 set to bridge mode) 1 Yes, and is assigned to br-lan
LAN 4 0 LAN br-lan (eth0.1 set to bridge mode) 1 Yes, and is assigned to br-lan
WAN 4 WAN eth1.2 2 Yes, depends on setting
N/A 5 / 5t (CPU for LAN) N/A eth0 1 No
N/A 6 / 6t (CPU for WAN) N/A eth1 2 No

Notes;

  • The br-lan (a pseudo interface) is what OpenWRT adds to the LAN / eth0.1 interface if it is configured to option type 'bridge' in /etc/config/network
  • If the LAN / eth0.1 interface is not set to option type 'bridge', then the IP Address is assigned to eth0.1
  • The setting of eth0.1 to bridge or not bridge (OpenWRT documentation indicates the only option type is bridge) does not affect connectivity to the switch. It does affect connectivity to the wireless ethernet adapter(s) (see the next note)
  • Wireless Ethernet Adapters / Interfaces in OpenWRT are not assigned an IP Address. Instead they are "bridged" to eth0 and the switch via a "pseudo" bridge.
  • The eth0.1 and eth1.2 are named for the sake of the VLAN they belong to. In OpenWRT, the .1, .2, or whatever .Number following a standard ethernet interface name like eth0, eth1, eth2, etc. factor into how VLANs operate. A VLAN labeled as 1 will send traffic to ethX.1, a label of 8 would send it to ethX.8, etc.
  • The eth0.1 Interface when configured as a bridge becomes br-lan
  • lo is the loopback interface, 127.0.0.1

Conceptual View of OpenWRT and the AC Series of Routers "Network System"

The AC Series of routers has 2 "Wired" Ethernet Adapters (built into the SoC (System on a Chip)), 3 Wireless Ethernet Adapters (discrete components from the SoS), and 1 Switch (connected to the 5 Ethernet Ports on the rear of the unit). Both the eth0 and eth1 Ethernet Adapters are connected to the switch at a TCP/IP level. The VLAN capability of the switch is used to separate / isolate the WAN port from the LAN ports. Wireless Adapters are connected to LAN / br-lan and eth0 via a "pseudo" bridge and are not assigned a discrete IP Address, instead using the IP Address of the LAN / br-lan interface.

Multiple IP Addresses assigned to a Single (AKA Alias or Aliases in OpenWRT)

In the /etc/config/network File example below two IP Addresses are assigned to the LAN Bridge / eth0.1 Interface, where A.B.C.D and W.X.Y.Z are place holders for an IP Address

# When using IFCONFIG, this interface will be displayed as br-lan1 and eth0.1 will not
# have an IP Address

config interface 'lan1'
        option type 'bridge'
        option ifname 'eth0.1'
        option proto 'static'
        option netmask '255.255.255.0'
        option ip6assign '60'
        option ipaddr 'A.B.C.D'

config interface 'lan2'
        option proto 'static'
        option ipaddr 'W.X.Y.Z'
        option netmask '255.255.255.0'
        # The ifname needs to be set to the br-lan1 name, not eth0.1
        option ifname 'br-lan1'

...and don't forget;

  • Edit, Firewall Settings, Assign firewall zone, ...LAN
  • Save and Apply
  • service network reload.

VLANs

For the AC Series, the ports as "seen" from OpenWRT*;

LAN Ports: Port 0, 1, 2, 3

WAN Port: Port 4

CPU Ethernet for LAN: Port 5 / 5t

CPU Ethernet for WAN: Port 6 / 6t

* NOTE: The above port numbers are how OpenWRT "sees" the ports. The physical labeling of the ports as numbered on the back of the router are reversed. IE, OpenWRT Port 3 is labeled as LAN 1 on the router label. This is possibly due to how Marvell numbers their switches and manufacturers like Linksys wishing to have the ports numbered left to right.

VLAN Related Commands

  • To show the bridge name: brctl show (use the OpenWRT GUI to configure)
  • To show the available switches: swconfig list (usually returns: switch0)
  • To show the current configuration: swconfig dev switch0 show
  • To show what can be configured: swconfig dev switch0 help (again, use the OpenWRT GUI to configure)
  • To show what is currently configured on router: ls -l /sys/class/net

More information from OpenWRT is available here.

Configuration File

/etc/config/network

LuCI GUI

Network, Switch

Configuring Individual Physical Ports with Unique IP Addresses on Separate VLANs

  • Configure an additional VLAN with LuCI GUI
  • Edit the /etc/config/network File as follows (VLAN number 9 was randomly chosen, and could be any number, but they need to match in all instances of the below example, IE, wherever there is a 9, use 5 or 4 in all the same places if using a different number);
Do NOT use any special characters in the "config interface 'WhatEverName'" field like a dot ( . ), dash ( - ), etc.

config device
	option type '8021q'
	option ifname 'eth0'
	option vid '9'
	option name 'LAN9'
 
config interface 'LAN9'
	option ifname 'eth0.9'
	option proto 'static'
	option ipaddr 'A.B.C.D'
	option netmask '255.255.255.0'
  • In the LuCI GUI, Network Interfaces, WhatEverNewName, Edit, Firewall Settings Tab, add it to the LAN Zone
  • Save and Apply in the LuCI GUI
  • Type: service network restart (as the Save and Apply apparently doesn't do that step) OR Restart Button in the LuCI GUI

Forwarding between VLANs

https://forum.openwrt.org/t/solved-routing-between-2-vlans/8847

Use the Network, Firewall LuCI GUI

Multiple WAN Ports with MWAN3

Be sure to read the Additional Notes section at the end of the MWAN3 Section

Installing

Install MWAN3: opkg install mwan3 luci-app-mwan3 (The luci-app-mwan3 is under Network, Load Balancing)

Optional: opkg install kmod-macvlan (A utility that allows a single port to function as two ports with two IP Addresses and different MAC Addresses. IE, the WAN port could be configured with two IP Addresses)

Configuring

First, make sure there are two functional WAN Ports with distinct IP Addresses. This can be configured with the below /etc/config/network example.

In LuCI, Load Balancing, Interfaces Tab, WhatEverNameOfInterface, MWAN Interface Configuration sub-tab, set the following (as a minium);

  • Enabled: Checked
  • Initial State: Online
  • Tracking Host Name IP Address: -.-.-.- (This is an IP Address to Ping to test whether the interface is up / working)

Members sub-tab is not really important in the below example.

Policy sub-tab;

  • The granular details of this sub-tab have to be configured in the /etc/config/mwan3 file as LuCI doesn't allow detailed configuration, just selecting existing policies
  • Set up two that represent each WAN Port

Rules sub-tab can be used to explicitly configure a client machine behind the router use a specific interface;

  • Source Address: Whatever device should use this interface
  • Destination address: 0.0.0.0/0 (if not configured it won't work properly)
  • Policy assigned: Whatever Policy that says use "interface X"
  • Sticky "suggests" that subsequent connections should use the same interface (in the below example it doesn't affect anything, but in some circumstances could affect secure connections to bank web sites as they are very picky about stuff, as it should be.)
Example

In the below example (/etc/config/mwan3) there are two physical WAN Ports (the WAN Port and Port 4 has been removed from the LAN VLAN and assigned to its own WAN VLAN and the WAN Firewall Zone in the /etc/config/network after the mwan3 example). It is a very simple example that has two WAN Ports. No load balancing or failover is configured. The example would be useful in a case where all client computers utilized one WAN for internet access and web servers could use the other WAN, so either WANs usage would not affect the other.;

Code Block
config rule 'https'
	option sticky '1'
	option dest_port '443'
	option proto 'tcp'
	option use_policy 'balanced'

config rule 'Win8_Test'
	option src_ip '192.168.2.50'
	option proto 'all'
	option dest_ip '0.0.0.0/0'
	option use_policy 'WAN2_only'
	option sticky '0'

config rule 'default_rule_v4'
	option dest_ip '0.0.0.0/0'
	option use_policy 'balanced'
	option family 'ipv4'

config globals 'globals'
	option local_source 'LAN1'
	option mmx_mask '0x3F00'
	option rtmon_interval '5'

config member 'WAN1_m1_w1'
	option interface 'WAN1'
	option metric '1'
	option weight '1'

config member 'WAN2_m2_w2'
	option interface 'WAN2'
	option weight '2'
	option metric '2'

config policy 'WAN1_only'
	list use_member 'WAN1_m1_w1'
	option last_resort 'unreachable'

config policy 'WAN2_only'
	list use_member 'WAN2_m2_w2'
	option last_resort 'unreachable'

config policy 'balanced'
	list use_member 'WAN1_m1_w1'
	list use_member 'WAN2_m2_w2'
	option last_resort 'unreachable'

config policy 'WAN1_WAN2'
	list use_member 'WAN1_m1_w1'
	list use_member 'WAN2_m2_w2'
	option last_resort 'unreachable'

config policy 'WAN2_WAN1'
	list use_member 'WAN1_m1_w1'
	list use_member 'WAN2_m2_w2'
	option last_resort 'unreachable'

config interface 'WAN1'
	option initial_state 'online'
	option family 'ipv4'
	option track_method 'ping'
	option reliability '1'
	option count '1'
	option size '56'
	option max_ttl '60'
	option check_quality '0'
	option timeout '2'
	option failure_interval '5'
	option down '3'
	option up '3'
	list track_ip '96.77.203.198'
	option recovery_interval '60'
	option interval '60'
	option enabled '1'
	list flush_conntrack 'connected'

config interface 'WAN2'
	option initial_state 'online'
	option family 'ipv4'
	option track_method 'ping'
	option reliability '1'
	option count '1'
	option size '56'
	option max_ttl '60'
	option check_quality '0'
	option timeout '2'
	option failure_interval '5'
	option recovery_interval '5'
	option down '3'
	option up '3'
	list track_ip '76.212.87.54'
	option interval '60'
	option enabled '1'

In the below /etc/config/network example, all of the other LAN, etc. configuration is not included. The -.-.-.- indicates one's own IP Address, subnet mask, etc. information be used. The below example uses Port 4 (as labeled on the back of the router, but is Port 0 from OpenWRT's "perspective") for the second WAN / WAN2 port. VLAN numbers can be anything, as long as when they are changed, they match in a similar manner to what is below and do not interfere with existing LAN VLANs. The metric for WAN1 is set lower so it is always favored for clients behind the router as long as it is functional.

Code Block
config device
	option type '8021q'
	option ifname 'eth1'
	option vid '11'
	option name 'WAN1'

config interface 'WAN1'
	option ifname 'eth1.11'
	option proto 'static'
	option ipaddr '-.-.-.-'
	option netmask '-.-.-.-'
	option gateway '-.-.-.-'
	list dns '-.-.-.-'
	list dns '-.-.-.-'
	option metric '10'

config device
	option type '8021q'
	option ifname 'eth1'
	option vid '12'
	option name 'WAN2'

config interface 'WAN2'
	option ifname 'eth1.12'
	option proto 'static'
	option ipaddr '-.-.-.-'
	option netmask '-.-.-.-'
	option gateway '-.-.-.-'
	list dns '-.-.-.-'
	list dns '-.-.-.-'
	option metric '20'

config switch
	option name 'switch0'
	option reset '1'
	option enable_vlan '1'

config switch_vlan
	option device 'switch0'
	option vlan '11'
	option ports '4 6t'
	option vid '11'

config switch_vlan
	option device 'switch0'
	option vlan '12'
	option ports '0 6t'
	option vid '12'
Additional Notes

Whenever the DNSMASQ service is started it overwrites the /tmp/resolve.conf file with it's own version of that same file. It will also delete any symbolic link at /tmp/resolv.conf which typically points to /tmp/resolv.conf.auto. When the DNSMASQ service is stopped it "politely" recreates that symbolic link. An explanation is given here: https://forum.openwrt.org/t/solved-dnsmasq-resolv-conf-inconsitent/13972/2 Basically the site is saying that if the DNSMASQ service is started and you have your own "DNS Service", why do you need to use external DNS Servers (which makes sense).

A side effect of the above behavior is it overwrites MWAN3 settings that are stored in /tmp/resolv.conf.auto. If one has custom external DNS servers enabled for multiple WAN ports they will no longer be used. This is not a flaw with OpenWRT, just a behavior to be aware of. If one needs to configure specific upstream DNS servers, any custom DNS servers configured with MWAN can be configured within DNSMASQ. Again, this is just something to be aware of.

The following is not an issue IF a custom /etc/dhcpd.conf file exists (IE, if the default OpenWRT method for configuring DHCPD is used via the /etc/config/dhcp file): There is a problem if one wishes to use DHCPD and NAMED / BIND instead of DNSMASQ as the DHCPD service is not as "polite" as the DNSMASQ service (NAMED / BIND does not cause any conflict). When the DHCPD service starts, as with DNSMASQ, the /tmp/resolv.conf file is replaced. The settings DHCPD configures in the file are the same as DNSMASQ. However, when the DHCPD service is stopped, as noted above, it is as "polite" as DNSMASQ because the symbolic link that directs /tmp/resolv.conf to /tmp/resolv.conf.auto is not recreated. This leaves the /tmp/resolv.conf file configured with the setting nameserver 127.0.0.1. This can be an issue with BIND / NAMED if it is not configured to "answer" (listen and do recursive lookups) on 127.0.01 IP Address. So make sure the BIND / NAMED configuration file includes 127.0.0.1 IP Address in both the allow-recursion and listen-on-port sections.

Oddly, when doing a Google, Bing, etc search for these three terms: "resolvfile" "openwrt" "isc_dhcpd" NOTHING exists on the internet. Until now that is.

Additional Information

https://openwrt.org/docs/guide-user/network/wan/multiwan/mwan3

DNS ( BIND / NAMED )

When installing, be sure to disable or uninstall DNSMASQ. Make sure DHCPD is installed if removing DNSMASQ (see DHCPD section below)

  • service dnsmasq stop
  • service dnsmasq disable

OR

  • opkg remove dnsmasq

OR

  • Use the LuCI GUI, under System, Software, Installed Tab to uninstall

OR

  • set the DNSMASQ port to Port 0 in /etc/config/dhcp dnsmasq section to disable DNS

Installation

opkg update

opkg install bind-server bind-tools (bind-tools includes: bind-rndc bind-check, plus dependencies are all installed)

Enable and start the service (all of this is done automatically when the above packages are installed;

  • service named enable (the OpenWRT documentation contains information that applies to older versions and states: enable /etc/init.d/named)
  • service named start

Check to see if the service is running: pidof named

Configuration

Configure via text files in /etc/bind/... (see example file below)

If using Slave Zones, make sure permissions are set correctly for the Directory;

  • chown bind /etc/bind/slaves
  • chgrp bind /etc/bind/slaves

This is the command line OpenWRT uses (CHROOT is not employed) in the /etc/init.d/named file: /usr/sbin/named -u bind -f -c /etc/bind/named.conf (-u = User, -f = Run in the Foreground not as a Daemon, -c = Configuration File)

  • To disable IPv6, add the following to the command line: -4

Logging: see section on OpenWRT System Logging

For additional information: https://openwrt.org/docs/guide-user/services/dns/bind (Note: The OpenWRT documentation makes references to /etc/named.conf, but the files are in /etc/bind/...)

For command line information: https://linux.die.net/man/8/named

For logging information: https://kb.isc.org/docs/aa-01526 and https://docstore.mik.ua/orelly/networking_2ndEd/dns/ch07_05.htm

Example Configuration;

Code Block
options {

	directory "/tmp";
	
		// If your ISP provided one or more IP addresses for stable 
		// nameservers, you probably want to use them as forwarders.  
		// Uncomment the following block, and insert the addresses replacing 
		// the all-0's placeholder.
	
		// forwarders {
		// 	0.0.0.0;
		// };
	
	auth-nxdomain no;    # conform to RFC1035
        
	allow-recursion {
    		W.X.Y.Z/24;
	};
	
	allow-transfer {
		A.B.C.D;
		};
	
	listen-on port 53 {
		A.B.C.D;
		};
	
	querylog yes;

};


// Use with the following rndc.conf in named.conf, adjusting the allow list as needed:
//
// Generate with this command: rndc-confgen
//
key "rndc-key" {
      algorithm hmac-sha256;
      secret "zrb7APg1fyNhfwr/c1Fy8slvbd7BkIAzw9U8gUoJE90=";
};

controls {
      inet 127.0.0.1 port 953
               allow { 127.0.0.1; } keys { "rndc-key"; };
};



// These Items are in the Default OpenWRT named.conf File
//
// be authoritative for the localhost forward and reverse zones, and for broadcast zones as per RFC 1912

zone "." {
	type hint;
	file "/etc/bind/db.root";
};

zone "localhost" {
	type master;
	file "/etc/bind/db.local";
};

zone "127.in-addr.arpa" {
	type master;
	file "/etc/bind/db.127";
};

zone "0.in-addr.arpa" {
	type master;
	file "/etc/bind/db.0";
};

zone "255.in-addr.arpa" {
	type master;
	file "/etc/bind/db.255";
};

//////////


zone "150.168.192.in-addr.arpa" {
	type slave;
	masters {
		A.B.C.D;
		};
	file "/etc/bind/slaves/A.B.C.D.rev";
	allow-query {
		A.B.C.D;
		};
	};



zone "WhatEverZone" {
	type slave;
	masters {
		A.B.C.D;
		};
	file "/etc/bind/slaves/WhatEverZone.hosts";
	allow-query {
		W.X.Y.Z/24;
		};
	};



zone "WhatEverZone" {
	type slave;
	masters port 53 {
		A.B.C.D;
		};
	file "/etc/bind/slaves/WhatEverZone.hosts";
	};
	


logging {
     channel default_log {
          file "/var/log/named/default" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity info;
     };

     channel zone_transfers_log {
          file "/tmp/log/named/zone_transfers" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
     };
     
     category notify { zone_transfers_log; };       
     category xfer-in { zone_transfers_log; };       
     category xfer-out { zone_transfers_log; };

};

Additional Information

Make sure the BIND / NAMED configuration file includes 127.0.0.1 IP Address in both the allow-recursion and listen-on-port sections. This can cause issues with DHCPD if it is not configured correctly. See the MWAN3 and DHCPD sections for additional information.

When operating a dual WAN router with multiple IP Addresses assigned to multiple interfaces using MWAN and a switch configured to operate three separate LAN subnets, there can be issues when restarting the router or network services. The solution is to also restart BIND / NAMED. This can be done automatically using the "hotplug.d" functionality available in OpenWRT (see https://openwrt.org/docs/guide-user/base-system/hotplug for additional information). Below is a short script to add in /etc/hotplug.d/iface/80-named;

#!/bin/sh

[ "$ACTION" = ifup ] || exit 0

/etc/init.d/named enabled && /etc/init.d/named stop && /etc/init.d/named start

Adding the following to the /etc/rc.local file may be necessary too, when restarting the router: /etc/init.d/named enabled && /etc/init.d/named stop && /etc/init.d/named start

DHCPD (AKA isc-dhcp-server-ipv4, etc.)

Make sure DNSMASQ is disabled, as noted in the above DNS Section.

Also make sure ODHCPD is disabled. According to OpenWRT documentation, ODHCPD is intended to be used for IPv6 DHCP services. However, it also has IPv4 DHCP capability which can interfere with DHCPD.

  • According to documentation in /etc/config/dhcp in the 'odhcpd' section, setting this directive in this manner causes ODHCPD to take over all DHCP duties from DNSMASQ (IPv4 and IPv6): option maindhcp '1'
  • Setting the same above setting to zero, option maindhcp '0', may lead one to believe that it disables ODHCPD. This is not the case. This setting, option maindhcp '0', turns off ODHCPD IPv4 DHCP functionality. IPv6 DHCP functionality remains intact. With either setting, it can interfere with DHCPD starting. So, do one of the following;
    • service odhcpd disable
    • opkg remove odhcpd odhcpd-ipv6only

There are two versions of DHCPD, ISC and KEA. ISC is the older server and KEA is the newer. For simple or small networks, ISC will work fine and eliminates some configuration considerations. Read here for more information: https://www.isc.org/kea/

Another item to be aware of is the somewhat convoluted way the DHCPD service is configured within the OpenWRT "UCI Infrastructure" (Google OpenWRT and UCI for additional information). It isn't as straight forward as DHCPD is in CentOS, or other Linux distributions. But there is a reason for this, so please keep reading.

Prerequisites & Things to Keep in Mind

Remember the /etc/resolv.conf file is a symbolic link to /tmp/resolv.conf. That means changes to the file will not be preserved when the router is rebooted. To make permanent changes for the /etc/resolv.conf file, make equivalent setting changes in the /etc/config/dhcpd file. See the end of this section for an exception.

DNSMASQ normally provides DHCP service (and DNS), so disable DHCP functionality for DNSMASQ, disable DNSMASQ, or uninstall DNSMASQ. If uninstalling DNSMASQ be sure to install the BIND / NAMED service to replace the DNS functionality DNSMASQ provides. If the DNSMASQ service is removed, the LuCI GUI interface for it remains as that part of the GUI seems to be built into the core LuCI services instead of being an add-on module.

The nice people at OpenWRT realized that since DNSMASQ provides default DHCP services, it might be nice if settings from the DNSMASQ service were used with DHCPD. They seemed to get part way there with that concept, but not all the way. The DHCPD service in OpenWRT does indeed extract information from the /etc/config/dhcp file (this is the OpenWRT DNSMAQ configuration file). However, the only information it extracts from the /etc/config/dhcp file are the settings that are added via the /etc/uci-defaults/dhcpd.defaults file when the DHCPD service is installed. An example is the option domain 'lan' setting in the "config dnsmasq" section of the /etc/config/dhcp file. That setting is used to configure the "domain" setting in the /etc/resolv.conf file (this is just a symbolic link to /tmp/resolv.conf). However, because that setting is not copied (nor set) to the " config isc_dhcpd 'isc_dhcpd' " section of the /etc/config/dhcp file during the installation of DHCPD, that setting dissapears from the /etc/resolv.conf file after DHCPD is installed. It can of course be added manually in the isc_dhcpd section of the dhcp file. In fact, the entire dnsmasq section is ignored as far a DHCP is concerned. Worse than that, several settings that are used for DNSMASQ such as server do not work in the isc_dhcpd section of the dhcp file. It would be useful if it did as the /etc/init.d/dhcpd startup script echos its own settings into the /etc/resolv.conf file. A nice feature OpenWRT might add to the DHCPD package would be to configure settings like server in the /etc/config/dhcp file to work instead of hard coding a change in the DHCPD startup script. The resolvfile setting doesn't work either. But it doesn't work for DNSMASQ either.

As noted at the beginning of this section, changes made in the /etc/resolv.conf file will not persist across reboots of a router. Some settings can be set in the /etc/config/dhcp file to overcome this. However, since the section for DHCPD in the /etc/config/dhcp does not respect some settings such as server or resolvfile the only way to change settings like that are in the /etc/init.d/ startup scripts.

Installation

Watch out for the package titled "dhcpcd", as the "d" at the end might lead one to believe the "d" stands for "daemon" (AKA service). It does not. It is client software, hence the "c" in the name of the package. See this for more information: https://openwrt.org/packages/pkgdata/dhcpcd

  • opkg update
  • opkg install isc-dhcp-server-ipv4

Configuration & Management

Default Configuration File used during DHCPD package installation (and is then erased once those settings are copied to the /etc/config/dhcp file): /uci-defaults/dhcp.defaults

Default Configuration File used by OpenWRT to control DNSMASQ and DHCPD: /etc/config/dhcp

Default Configuration File (remember, this is a temporary file, so settings will not persist across router reboots): /tmp/run/dhcpd.conf

The Default Configuration File can be over-ridden by placing the DHCPD configuration file here: /etc/dhcpd.conf

Default Leases File: /tmp/dhcpd.leases (an odd recommendation to make, but even though it is in the /tmp directory, delete this file before using DHCPD, it will be recreated automatically)

DHCPD Executable / Binary File: /usr/sbin/dhcpd

Command for checking DHCPD configuration files: dhcpd -cf WhatEverConfigurationPathAndFile -lf /WhatEverPathToDHCPdLeasesFile

If one wants to stay within the OpenWRT methodology of configuring the DHCPD service, it must be done by putting settings in the config isc_dhcpd 'isc_dhcpd' section of the /etc/config/dhcp File. Why? One, as noted above settings made here will not persist across reboots. Plus the /tmp/run/dhcpd.conf file is overwritten every time the DHCPD Service is restarted with settings from the /etc/config/dhcp File. And two, the dhcpd.conf file is stored in the /tmp Directory so settings put in that file will be lost if the router is restarted. This makes it impossible to use a GUI like Webmin to manage DHCP settings. But...

Since there is no LuCI GUI interface for DHCPD, the options available for the DHCPD service in the /etc/config/dhcp file are not documented (Note, the "DHCP Settings at the following website apply to DNSMASQ, not DHCPD: https://openwrt.org/docs/guide-user/base-system/dhcp) , and the settings that do exist seem to be "wonky", there is very little reason to remain locked inside of the OpenWRT DHCPD configuration paradigm. That requires changing settings in the /etc/init.d/dhcpd startup script.

And it opens a whole new world in the ease of configuring and managing DHCPD with Webmin, persistent settings in a dhcpd.conf style file that is similar to other Linux distributions, etc. The following steps make this possible (plus it is fairly easy thanks to the way the /etc/init.d/dhcpd startup script is written);

  • Create an /etc/dhcpd.conf file (the /etc/init.d/dhcpd script has provisions to search for this file)
  • There is NO need to modify the /etc/init.d/dhcpd startup script file as one might think, because as noted above, the startup script has provisions for this situation;
    • Orginal line: config_file=/tmp/run/dhcpd.conf
    • New line: config_file=/etc/dhcpd.conf

But also keep in mind the settings changes in the /etc/init.d/dhcpd startup script only affect the DHCPD service. The /etc/resolv.conf File still derives its settings from the /etc/config/dhcp File when the DHCPD service is restarted or the router is rebooted (same for DNSMASQ). IE, the /etc/config/dhcp File should not be completely dismissed as useless.

Restricting the DHCPD Service to only Answer / Listen on Desired Interfaces

To restrict the DHCPD service to a specific interface, edit the /etc/init.d/dhcpd file, scroll way down to the start_service section, and look for the following line;

  • procd_set_param command $PROG -q -f -cf $config_file -lf $lease_file $dhcp_ifs

Change it in similar manner to the below examples;

  •    procd_set_param command $PROG WhatEverAdapterName WhatEverOtherAdapterName -q -f -cf $config_file -lf $lease_file $dhcp_ifs
  •    procd_set_param command $PROG eth0.1 br-LAN1_1 -q -f -cf $config_file -lf $lease_file $dhcp_ifs

Many sites suggest that creating a blank / empty zone for the subnet (on a multi-homed device) will make it so DHCPD doesn't answer for those interfaces. But testing has prooven otherwise. The below settings in /etc/dhcpd/dhcpd.conf will 00000000000000000000000000 prevent the DHCPD service from answering on the interface associated with the W.X.Y.Z IP Address;

subnet W.X.Y.Z netmask 255.255.255.0 {
}

The Edit Network Interfaces Button and Interfaces File Type setting in Webmin will not work with OpenWRT.

Special Note

Whenever the DNSMASQ service is started it overwrites the /tmp/resolve.conf file with it's own version of that same file. It will also delete any symbolic link at /tmp/resolv.conf which typically points to /tmp/resolv.conf.auto. When the DNSMASQ service is stopped it "politely" recreates that symbolic link. An explanation is given here: https://forum.openwrt.org/t/solved-dnsmasq-resolv-conf-inconsitent/13972/2

Not so for DHCPD (see the above end of the MWAN section above for more information on this subject)

Another irritating issue is that no method to manually configure a nameserver setting within the /etc/resolv.conf (this file is a symbolic link to /tmp/resolv.conf) if using the /etc/config/dhcp method of configuring DHCPD (HINT: Use the above described method of having a custom /etc/dhcpd.conf file). The /etc/resolv.conf file is overwritten each time the DHCPD (or DNSMASQ) service is restarted. The /etc/init.d/dhcp startup script sets the nameserver variable in /etc/resolv.conf with this line: echo "nameserver 127.0.0.1" >> /tmp/resolv.conf. Even if the echo command in the startup script is disabled, setting option server 'W.X.Y.Z' in the isc_dhcpd 'isc_dhcpd' section does not work. The only way to set nameserver in the /etc/resolv.conf file is to manually edit the /etc/init.d/dhcp startup script line that echos the setting into resolv.conf. Again, all of this paragraph assumes a custom /etc/dhcpd.conf file is NOT being used (again, HINT: Use a custom /etc/dhcpd.conf file, can't write it enough).

Additional Notes

There are a couple of items lacking in the OpenWRT DHCPD /etc/init.d/dhcpd startup script file;

  • The PID file that is created in /var/run/dhcpd.pid file is created when the service initially starts and never goes away, even if the service is stopped.
  • If a custom /etc/dhcpd.conf file is NOT being used and the standard OpenWRT method of using /etc/config/dhcp method is used (again, HINT: Use a custom /etc/dhcpd.conf file), the DHCPD startup script erases the symbolic link that connects /tmp/resolv.conf --> /tmp/resolv.conf.auto in favor of its own custom /tmp/resolv.conf file (/etc/resolv.conf). This can break DNS settings for networking in general and MWAN3.

Solution? Add the following lines to the /etc/init.d/dhcpd startup script to solve the above mentioned issue, plus some optional stuff;

# In the start_service() section after this line: config_file="/etc/dhcpd.conf"
# Add these two lines (completely option, not necessary);

echo -n $"Starting ISC-DHCPD with /etc/dhcpd.conf file"
echo



stop_service()
	{
	ln -sf "/tmp/resolv.conf.auto" /tmp/resolv.conf
	rm /var/run/dhcpd.pid
	}

The ln command corrects the symbolic link issue mentioned above. And the rm command corrects the PID file issue that never goes away, again mentioned above. Also note that if the DHCPD package is ever updated, the script will need to be modified again. A startup script could be written, but haven't had time to write that yet. This post gives a fairly goot hint on how to write it: https://askubuntu.com/questions/77149/how-to-find-text-and-replace-that-line-if-exists-with-terminal-otherwise-just-ap Although regular expressions wouldn't be necessary, just a check to see if "stop_service" exists anywhere in the dhcpd startup script and if it doesn't, insert it at the end.

Also keep in mind the LuCI GUI interface, under Network, Interface, Edit Button for X Interface, DHCP Tab will always show "No DHCP Server configured for this interface". This is because the LuCI GUI is not able to detect DHCPD (only DNSMASQ and ODHCPD)

As with BIND / NAMED, when operating a dual WAN router with multiple IP Addresses assigned to multiple interfaces using MWAN and a switch configured to operate three separate LAN subnets, there can be issues when restarting the router or network services. The solution is to also restart DHCPD. This can be done automatically using the "hotplug.d" functionality available in OpenWRT (see https://openwrt.org/docs/guide-user/base-system/hotplug for additional information). Below is a short script to add in /etc/hotplug.d/iface/70-dhcpd;

#!/bin/sh

[ "$ACTION" = ifup ] || exit 0

/etc/init.d/dhcpd enabled && /etc/init.d/dhcpd stop && /etc/init.d/dhcpd start

Adding the following to the /etc/rc.local file may be necessary too, when restarting the router: /etc/init.d/dhcpd enabled && /etc/init.d/dhcpd stop && /etc/init.d/dhcpd start

SOCKD (Dante)

It exists. And that's about it. There is some indication in the past the package was more complete, but as of 2020, the SOCKD package is single binary file (sockd).

Installation: opkg install sockd

File included: /usr/sbin/sockd

Log file (after the below configuration is done): /var/log/sockd.log (/tmp/log/sockd.log)

Configuration: Nothing is included in the OpenWRT package. It all has to be configured manually. Thankfully, some really nice person (bjonas), created all of the configuration files that should be included in the SOCKD package for OpenWRT. See this page for the "raw" / basic information: https://dev.archive.openwrt.org/ticket/21341#no1

The really amazing thing is that if one Googles "openwrt" and "sockd", there are a grand total of 73 results (with most of those results being useless trash aggregation websites whose creators do not deserve to have air to breathe). Most Google results and searches of OpenWRT packages for a SOCKS5 proxy return a lot of stuff related to client SOCKs software (and not really abundantly clear that it is client software as opposed to a SOCKS server service / daemon). DD-WRT has a functional version of the package, so why not OpenWRT? The DD-WRT init.d script is very basic and relies on other functionality from DD-WRT to function, so isn't very useful for OpenWRT.

The configuration file written by "bjonas" is below, tested, and it functions. The below script should be put in this file: /etc/init.d/sockd. This allows the service to be started, stopped, etc. with the OpenWRT service command. One modification from the original script was made. The configuration file was moved from /etc/sockd.conf to /etc/sockd/sockd.conf and the appropriate line in the below script was modified from the original version.;

#!/bin/sh /etc/rc.common

START=90

USE_PROCD=1
PROG=/usr/sbin/sockd

CONFIGFILE="/var/etc/sockd.conf"

xappend() {
        local value="$1"

        echo "${value#--}" >> $CONFIGFILE
}

append_parm() {
        local section="$1"
        local option="$2"
        local switch="$3"
        local defval="$4"
        local _loctmp
        config_get _loctmp "$section" "$option"
        if [ -z "$_loctmp" ]; then
                [ -z "$defval" ] && return 0
                xappend "$switch:$defval"
        else
                xappend "$switch:$_loctmp"
        fi
}

sockd(){
        local cfg="$1"
        append_parm "$cfg" "clientmethod" "--clientmethod"
        append_parm "$cfg" "method" "--method"
        append_parm "$cfg" "user_privileged" "--user.privileged" "root"
        append_parm "$cfg" "user_notprivileged" "--user.notprivileged" "nobody"
        append_parm "$cfg" "logoutput" "--logoutput" "syslog"
        local _extif _intif _extip _intip
        config_get _extif "$cfg" "external"
        [ -z "$_extif" ] && _extif="wan"
        config_get _intif "$cfg" "internal"
        [ -z "$_intif" ] && _intif="lan"
        network_flush_cache
        network_get_ipaddr _extip $_extif
        xappend "--external:$_extip"
        network_get_ipaddr _intip $_intif
        local _port
        config_get _port "$cfg" "port" "1080"
        xappend "--internal:$_intip port = $_port"
        echo >> $CONFIGFILE
}

service_triggers() {
        procd_add_reload_trigger "sockd"
#       procd_add_network_trigger "wan"|"pppoe-wan"
}

boot() {
        # Will be launched through hotplug
        return 0
}

start_service() {
        include /lib/functions

        config_load sockd

        procd_open_instance
        procd_set_param command $PROG -f $CONFIGFILE
        procd_set_param file $CONFIGFILE
        procd_set_param netdev wan
        procd_set_param respawn
        procd_close_instance

        echo "# auto-generated config file from /etc/config/sockd" > $CONFIGFILE
        [ -f /etc/sockd/sockd.conf ] && {
                cat /etc/sockd/sockd.conf >> $CONFIGFILE
        }

        config_foreach sockd sockd
}

reload_service() {
        return 0
}

stop_service() {
        return 0
}

After saving the above information, the SOCKD service should be displayed when the OpenWRT service command is typed. There are two ways to configure the SOCKD / Dante SOCKS5 proxy. With a configuration file (/etc/sockd/sockd.conf) or a standard OpenWRT configuration file in /etc/config/sockd. All of this capability is made possible by the startup script created by bjonas (there are indications the version of the script may have been based on past packages from OpenWRT). If using the sockd.conf method, make sure the /etc/config/sockd file is blank / empty as directives in that file will be included in addition to anything in the sockd.conf file. Below is the /etc/config/sockd file (again, don't use it if the sockd.conf file is used;

config sockd
        option external                 'wan'
        option internal                 'lan'
        option clientmethod             'none'
        option method                   'none'
        option user_privileged          'root'
        option user_notprivileged       'nobody'
        option logoutput                'syslog'

Below is a functional /etc/sockd/sockd.conf file. Change the W.X.Y.Z IP Address to match whatever subnets / IP Addresses are used. Some sections of the below configuration file could be combined and are somewhat redundant. However, to match the original example it was kept in this format. The configuration is not restrictive and essentially allows all connectivity from the source subnet to anywhere via the SOCKD server / daemon.

logoutput: stderr /var/log/sockd.log

# LAN IP Address of router
internal: W.X.Y.Z port = 1080

# WAN Interface name for router (ifconfig, whichever interface is configured with an external IP Address)
# Note, this won't work if one's router is behind another router unless ports are forwarded from the "perimeter" router)
external: eth1.2

socksmethod: username none #rfc931

clientmethod: none

# Client subnet
# 0.0.0.0/0 equates to "Anywhere"
client pass {
        from: W.X.Y.Z/24 to: 0.0.0.0/0
	log: error # connect disconnect
}

socks pass {
        from: 0.0.0.0/0 to: W.X.Y.Z/24
        command: bindreply udpreply
        log: connect error
}

socks pass {  
        from: W.X.Y.Z/24 to: 0.0.0.0/0
        command: bind connect udpassociate bindreply udpreply
        log: error # connect disconnect iooperation
}

As for starting the service, bjonas elected to create a "hot plug" method. Below is the configuration file that should be placed here: /etc/hotplug.d/iface/60-sockd;

#!/bin/sh

[ "$ACTION" = ifup ] || exit 0

/etc/init.d/sockd enabled && /etc/init.d/sockd start

Executing the service sockd start command should start the service at this point. The log file in /var/log/sockd.log will indicate any configuration issues. Additionally the service / daemon can be run with this command line for troubleshooting: sockd -f /etc/sockd/sockd.conf

LAMP (sort of) - Web Server (Apache, LighttpD, Nginx, and / or uHTTPd) MariaDB (MySQL), and PHP

OpenWRT has four different web server platforms available. Apache, LighttpD, and Nginx are all full featured, whereas uHTTPd is more limited in its functionality. uHTTPd also serves as the web server for the LuCI GUI interface for OpenWRT. Apache does not have CGI or FastCGI built into the binary executable, but both Lighttpd and Nginx have CGI and FastCGI capability built in, making addon modules unecessary.

Apache

The Apache package in OpenWRT appears to only have CGI capability as the FastCGI module is not available. However, there are additional proxy modules included with Apache in OpenWRT that allow for PHP-FPM functionality with FastCGI.

Installation for Apache

opkg update

opkg install apache apache-utils apache-mod-ssl

Configuration for Apache

There is no LuCI GUI interface, so use text configuration files and / or Webmin (see below section on Webmin)

  • Initilization Script: /etc/init.d/apache2
  • Configuration File: /etc/apache2/apache2.conf
  • Default Server Root: /usr
  • Default Document Root: /usr/share/apache2/htdocs
  • Executables / Binaries: /usr/lib/apache2
  • User / Group (/etc/group): apache / apache

Below is working configuration file for Apache with CGI capability;

Code Block
ServerRoot "/usr"


Listen 192.168.2.66:80
Listen 192.168.15.66:80
Listen 192.168.22.66:80
Listen 96.77.203.196:80
Listen 76.212.87.51:80



TimeOut 3600






#LoadModule mpm_event_module lib/apache2/mod_mpm_event.so
LoadModule mpm_prefork_module lib/apache2/mod_mpm_prefork.so
#LoadModule mpm_worker_module lib/apache2/mod_mpm_worker.so
LoadModule authn_file_module lib/apache2/mod_authn_file.so
#LoadModule authn_dbm_module lib/apache2/mod_authn_dbm.so
#LoadModule authn_anon_module lib/apache2/mod_authn_anon.so
LoadModule authn_dbd_module lib/apache2/mod_authn_dbd.so
#LoadModule authn_socache_module lib/apache2/mod_authn_socache.so
LoadModule authn_core_module lib/apache2/mod_authn_core.so
LoadModule authz_host_module lib/apache2/mod_authz_host.so
LoadModule authz_groupfile_module lib/apache2/mod_authz_groupfile.so
LoadModule authz_user_module lib/apache2/mod_authz_user.so
#LoadModule authz_dbm_module lib/apache2/mod_authz_dbm.so
#LoadModule authz_owner_module lib/apache2/mod_authz_owner.so
#LoadModule authz_dbd_module lib/apache2/mod_authz_dbd.so
LoadModule authz_core_module lib/apache2/mod_authz_core.so
#LoadModule authnz_ldap_module lib/apache2/mod_authnz_ldap.so
LoadModule access_compat_module lib/apache2/mod_access_compat.so
LoadModule auth_basic_module lib/apache2/mod_auth_basic.so
#LoadModule auth_form_module lib/apache2/mod_auth_form.so
#LoadModule auth_digest_module lib/apache2/mod_auth_digest.so
#LoadModule allowmethods_module lib/apache2/mod_allowmethods.so
#LoadModule file_cache_module lib/apache2/mod_file_cache.so
#LoadModule cache_module lib/apache2/mod_cache.so
#LoadModule cache_disk_module lib/apache2/mod_cache_disk.so
#LoadModule cache_socache_module lib/apache2/mod_cache_socache.so
#LoadModule socache_shmcb_module lib/apache2/mod_socache_shmcb.so
#LoadModule socache_dbm_module lib/apache2/mod_socache_dbm.so
#LoadModule socache_memcache_module lib/apache2/mod_socache_memcache.so
#LoadModule socache_redis_module lib/apache2/mod_socache_redis.so
#LoadModule watchdog_module lib/apache2/mod_watchdog.so
#LoadModule macro_module lib/apache2/mod_macro.so
#LoadModule dbd_module lib/apache2/mod_dbd.so
#LoadModule dumpio_module lib/apache2/mod_dumpio.so
#LoadModule echo_module lib/apache2/mod_echo.so
#LoadModule buffer_module lib/apache2/mod_buffer.so
#LoadModule data_module lib/apache2/mod_data.so
#LoadModule ratelimit_module lib/apache2/mod_ratelimit.so
LoadModule reqtimeout_module lib/apache2/mod_reqtimeout.so
#LoadModule ext_filter_module lib/apache2/mod_ext_filter.so
#LoadModule request_module lib/apache2/mod_request.so
#LoadModule include_module lib/apache2/mod_include.so
LoadModule filter_module lib/apache2/mod_filter.so
#LoadModule reflector_module lib/apache2/mod_reflector.so
#LoadModule substitute_module lib/apache2/mod_substitute.so
#LoadModule sed_module lib/apache2/mod_sed.so
#LoadModule charset_lite_module lib/apache2/mod_charset_lite.so
#LoadModule deflate_module lib/apache2/mod_deflate.so
LoadModule xml2enc_module lib/apache2/mod_xml2enc.so
LoadModule proxy_html_module lib/apache2/mod_proxy_html.so
LoadModule mime_module lib/apache2/mod_mime.so
#LoadModule ldap_module lib/apache2/mod_ldap.so
LoadModule log_config_module lib/apache2/mod_log_config.so
#LoadModule log_debug_module lib/apache2/mod_log_debug.so
#LoadModule log_forensic_module lib/apache2/mod_log_forensic.so
#LoadModule logio_module lib/apache2/mod_logio.so
#LoadModule lua_module lib/apache2/mod_lua.so
LoadModule env_module lib/apache2/mod_env.so
LoadModule mime_magic_module lib/apache2/mod_mime_magic.so
#LoadModule expires_module lib/apache2/mod_expires.so
LoadModule headers_module lib/apache2/mod_headers.so
#LoadModule usertrack_module lib/apache2/mod_usertrack.so
#LoadModule unique_id_module lib/apache2/mod_unique_id.so
LoadModule setenvif_module lib/apache2/mod_setenvif.so
LoadModule version_module lib/apache2/mod_version.so
#LoadModule remoteip_module lib/apache2/mod_remoteip.so
#LoadModule proxy_module lib/apache2/mod_proxy.so
#LoadModule proxy_connect_module lib/apache2/mod_proxy_connect.so
#LoadModule proxy_ftp_module lib/apache2/mod_proxy_ftp.so
#LoadModule proxy_http_module lib/apache2/mod_proxy_http.so
#LoadModule proxy_fcgi_module lib/apache2/mod_proxy_fcgi.so
#LoadModule proxy_scgi_module lib/apache2/mod_proxy_scgi.so
#LoadModule proxy_uwsgi_module lib/apache2/mod_proxy_uwsgi.so
#LoadModule proxy_fdpass_module lib/apache2/mod_proxy_fdpass.so
#LoadModule proxy_wstunnel_module lib/apache2/mod_proxy_wstunnel.so
#LoadModule proxy_ajp_module lib/apache2/mod_proxy_ajp.so
#LoadModule proxy_balancer_module lib/apache2/mod_proxy_balancer.so
#LoadModule proxy_express_module lib/apache2/mod_proxy_express.so
#LoadModule proxy_hcheck_module lib/apache2/mod_proxy_hcheck.so
#LoadModule session_module lib/apache2/mod_session.so
#LoadModule session_cookie_module lib/apache2/mod_session_cookie.so
#LoadModule session_crypto_module lib/apache2/mod_session_crypto.so
#LoadModule session_dbd_module lib/apache2/mod_session_dbd.so
#LoadModule slotmem_shm_module lib/apache2/mod_slotmem_shm.so
#LoadModule slotmem_plain_module lib/apache2/mod_slotmem_plain.so
#LoadModule ssl_module lib/apache2/mod_ssl.so
#LoadModule dialup_module lib/apache2/mod_dialup.so
#LoadModule http2_module lib/apache2/mod_http2.so
#LoadModule md_module lib/apache2/mod_md.so
#LoadModule lbmethod_byrequests_module lib/apache2/mod_lbmethod_byrequests.so
#LoadModule lbmethod_bytraffic_module lib/apache2/mod_lbmethod_bytraffic.so
#LoadModule lbmethod_bybusyness_module lib/apache2/mod_lbmethod_bybusyness.so
#LoadModule lbmethod_heartbeat_module lib/apache2/mod_lbmethod_heartbeat.so
LoadModule unixd_module lib/apache2/mod_unixd.so
#LoadModule heartbeat_module lib/apache2/mod_heartbeat.so
#LoadModule heartmonitor_module lib/apache2/mod_heartmonitor.so
#LoadModule dav_module lib/apache2/mod_dav.so
LoadModule status_module lib/apache2/mod_status.so
LoadModule autoindex_module lib/apache2/mod_autoindex.so
#LoadModule asis_module lib/apache2/mod_asis.so
#LoadModule info_module lib/apache2/mod_info.so
#LoadModule suexec_module lib/apache2/mod_suexec.so
<IfModule !mpm_prefork_module>
#LoadModule cgid_module lib/apache2/mod_cgid.so
</IfModule>
<IfModule mpm_prefork_module>
LoadModule cgi_module lib/apache2/mod_cgi.so
</IfModule>
#LoadModule dav_fs_module lib/apache2/mod_dav_fs.so
#LoadModule dav_lock_module lib/apache2/mod_dav_lock.so
LoadModule vhost_alias_module lib/apache2/mod_vhost_alias.so
#LoadModule negotiation_module lib/apache2/mod_negotiation.so
LoadModule dir_module lib/apache2/mod_dir.so
LoadModule actions_module lib/apache2/mod_actions.so
#LoadModule speling_module lib/apache2/mod_speling.so
#LoadModule userdir_module lib/apache2/mod_userdir.so
LoadModule alias_module lib/apache2/mod_alias.so
LoadModule rewrite_module lib/apache2/mod_rewrite.so




<IfModule unixd_module>

User apache
Group apache

</IfModule>

ServerName wrt3200acm.fullspectrum.lan:80


DocumentRoot "/usr/share/apache2/htdocs"
<Directory "/usr/share/apache2/htdocs">
	DirectoryIndex index.php index.html index.htm

    Options Indexes FollowSymLinks

    AllowOverride None

    Require all granted
</Directory>


<IfModule dir_module>
    DirectoryIndex index.html
</IfModule>

<Files ".ht*">
    Require all denied
</Files>


ErrorLog "/var/log/apache2/error_log"


LogLevel warn

<IfModule log_config_module>
 
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common

    <IfModule logio_module>
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>


    CustomLog "/var/log/apache2/access_log" common


</IfModule>

<IfModule alias_module>

    ScriptAlias /cgi-bin/ "/usr/share/apache2/cgi-bin/"

</IfModule>

<IfModule cgid_module>
Scriptsock /var/run/cgid.sock
</IfModule>


<Directory "/cgi-bin">
    AllowOverride None
    Options None
    Require all granted
</Directory>

<IfModule headers_module>

    RequestHeader unset Proxy early
</IfModule>

<IfModule mime_module>
 
    TypesConfig /etc/apache2/mime.types


    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz


</IfModule>

MIMEMagicFile /etc/apache2/magic



# Supplemental configuration
#
# The configuration files in the /etc/apache2/extra/ directory can be 
# included to add extra features or to modify the default configuration of 
# the server, or you may simply copy their contents here and change as 
# necessary.

# Server-pool management (MPM specific)
#Include /etc/apache2/extra/httpd-mpm.conf

# Multi-language error messages
#Include /etc/apache2/extra/httpd-multilang-errordoc.conf

# Fancy directory listings
#Include /etc/apache2/extra/httpd-autoindex.conf

# Language settings
#Include /etc/apache2/extra/httpd-languages.conf

# User home directories
#Include /etc/apache2/extra/httpd-userdir.conf

# Real-time info on requests and configuration
#Include /etc/apache2/extra/httpd-info.conf

# Virtual hosts
#Include /etc/apache2/extra/httpd-vhosts.conf

# Local access to the Apache HTTP Server Manual
#Include /etc/apache2/extra/httpd-manual.conf

# Distributed authoring and versioning (WebDAV)
#Include /etc/apache2/extra/httpd-dav.conf

# Various default settings
#Include /etc/apache2/extra/httpd-default.conf

# Configure mod_proxy_html to understand HTML4/XHTML1
<IfModule proxy_html_module>
Include /etc/apache2/extra/proxy-html.conf
</IfModule>

# Secure (SSL/TLS) connections
#Include /etc/apache2/extra/httpd-ssl.conf
#
# Note: The following must must be present to support
#       starting without SSL on platforms with no /dev/random equivalent
#       but a statically compiled-in mod_ssl.
#
<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
</IfModule>

<Files ".user.ini">
    <IfModule mod_authz_core_module>
        Require all denied
    </IfModule>
    <IfModule !mod_authz_core_module>
        Order allow,deny
        Deny from all
        Satisfy All
    </IfModule>
</Files>


<IfModule alias_module>
	ScriptAlias /php /usr/bin
</IfModule>

# Either the AddType or AddHandler Directive can be used
# AddType application/x-httpd-php .php
AddHandler application/x-httpd-php .php
Action application/x-httpd-php /php/php-cgi


<Directory "/usr/bin">

	AllowOverride None
	Options none
	Order allow,deny
	Allow from all

</Directory>


<Directory "/usr/share/apache2/htdocs/phpMyAdmin">

	AllowOverride All
	Options none
	Order allow,deny
	Allow from all

</Directory>

    <FilesMatch "\.php$">
        SetHandler application/x-httpd-php
    </FilesMatch>
    <FilesMatch "\.phps$">
        SetHandler application/x-httpd-php-source
    </FilesMatch>

The above configuration file also includes settings for PHP and CGI.


Also make sure the following lines exist or are not commented out in the /etc/apache2/apache2.conf file for CGI functionality;

LoadModule mpm_prefork_module lib/apache2/mod_mpm_prefork.so
LoadModule cgi_module lib/apache2/mod_cgi.so

ScriptAlias /cgi-bin /usr/share/apache2/cgi-bin

<Directory /cgi-bin>
    AllowOverride None
    Options None
    Require all granted
</Directory>

Set permissions for the Apache document directory;

chown -R apache:apache /usr/share/apache2

find /usr/share/apache2 -type d -exec chmod 755 {} \;
find /usr/share/apache2 -type f -exec chmod 644 {} \;
Notes for Apache

In other installations, such as Redhat or CentOS, apache or apache2 is referred to as HTTPD in binary / executables, configuration files, commands, etc.

To test Apache configuration file: apachectl configtest

The below settings do NOT work or are NOT available in OpenWRT for Apache, so do NOT attempt to enable them in /etc/apache2/apache2.conf

  • LoadModule proxy_fcgi_module lib/apache2/mod_proxy_fcgi.so (Module does NOT exist for OpenWRT)
  • LoadModule proxy_scgi_module lib/apache2/mod_proxy_scgi.so (Module does NOT exist for OpenWRT)
  • LoadModule cgid_module lib/apache2/mod_cgid.so (does NOT seem to work, even when setting the ScriptSock Directive)

Lighttpd

In the OpenWRT packages Lighttpd has CGI and FastCGI capability unlike Apache which only has CGI capability. OpenWRT has PHP 7 packages for CGI and FastCGI (opkg install php7-fastcgi) available to make use of the Lighttpd capabilities. The FastCGI capability also allows Lighttpd to utilize the PHP FPM capbability covered in several sections below.

Installation of Lighttpd

opkg update

opkg install lighttpd lighttpd-mod-cgi lighthttpd-mod-fastcgi

Configuration of Lighttpd

Configuration Files: /etc/lighttpd/lighttpd.conf

Additional Configuration Files: /etc/lighttpd/conf.d (see PHP sections below for additional information)

Service Command: service lighttpd (stop / start / restart)

Be Aware;

  • The OpenWRT Lighttpd package sets the default document directory to the same directory used by uHTTPd (the web service that provides the LuCI GUI). It is recommended modify the setting to a directory such as /usr/share/lighttpd (which follows the Apache directory convention used by OpenWRT).
  • The port number is set to 81 by default. This is done so as to not interfere with uHTTPd and LuCI. This can be changed to port 80, but the uHTTPd port must be changed to a different (non port 80) port in /etc/config/uhttpd and the uhttpd service restarted.

Below is a working /etc/lighttpd/lighttpd.conf configuration file;

Code Block
server.document-root        = "/usr/share/lighttpd"
server.port                 = 80
server.upload-dirs          = ( "/tmp" )
server.errorlog             = "/var/log/lighttpd/error.log"
server.pid-file             = "/var/run/lighttpd.pid"
server.username             = "http"
server.groupname            = "www-data"

index-file.names            = ( "index.php", "index.html",
                                "index.htm", "default.htm",
                              )

#dir-listing.activate	    = "enable"
#server.dir-listing          = "enable"
#dir-listing.encoding        = "utf-8"

# Prevents a web browser from offering to download the file in text form
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )

# To enable PHP with the Lighttpd Module, this line is the minimum necessary for it to function and should be placed in the /etc/lighttpd/conf.d/30-cgi.conf file;
# cgi.assign			= ( ".php"  => "/usr/bin/php-cgi" )

### Options that are useful but not always necessary:
#server.chroot               = "/"
#server.bind                 = "localhost"
#server.tag                  = "lighttpd"
#server.errorlog-use-syslog  = "enable"
#server.network-backend      = "writev"

### Use IPv6 if available
#include_shell "/usr/share/lighttpd/use-ipv6.pl"

include "/etc/lighttpd/mime.conf"
include "/etc/lighttpd/conf.d/*.conf"

The above configuration file also contains settings relevant to additional items such as CGI and PHP which is covered in several below sections.

A new user (http in /etc/passwd) and a new group (www-data in /etc/group) are configured, so be sure to change the permissions and owner appropriately for a new root directory for Lighttpd;

chown -R http:www-data /usr/share/lighttpd

find /usr/share/lighttpd -type d -exec chmod 755 {} \;
find /usr/share/lighttpd -type f -exec chmod 644 {} \;
Notes for Lighttpd

To see the various modules compiled within the Lighttpd binary: lighttpd -V (that's a CAPITAL "V")

CGI and FastCGI

See the below PHP section for Lighttpd

php-cgi -b 127.0.0.1:9123

PHP

First the bad news (which really isn't bad news): The mod_php module is not available for Apache. But that's OK, because there are several Apache Proxy Modules and PHP Modules that allow for PHP functionality with Apache using CGI, FastCGI, and PHP-FPM (see below for several external links that discuss the differences between the technologies).

The php-cgi (opkg install php7-cgi) package is available from OpenWRT and is necessary for PHP function with any of the above mentioned web servers. The guide at: https://openwrt.org/docs/guide-user/services/webserver/http.apache leaves out a LOT of Apache configuration that is necessary to have PHP function correctly. Additionally, it adds some items that do not seem necessary. Of course this could be due to changes in the settings for the Apache package over the years or differences between router platforms, so the previous comments are not a criticism of OpenWRT or its documentation.

PHP Installation

opkg update

opkg install php7 php7-cgi php7-cli php7-fastcgi php7-fpm The php-cli (PHP Command Line) is not necessary, but is useful for troubleshooting. Most examples utilizing the PHP command line program refer to it as just php, not php-cli. OpenWRT installs it as php-cli, so instead of having to remember that, it maybe useful to create a symbolic link with this command: ln -s /usr/bin/php-cli /usr/bin/php

PHP Configuration in /etc/php.ini

Comment out or change the line in /etc/php.ini;

  • doc_root

OR

  • #doc_root = WhatEver

The guide at: https://openwrt.org/docs/guide-user/services/webserver/http.apache states the following should be put in the php.ini file, but is unnecessary;

  • extension=gd.so

OR

  • extension=/usr/lib/php/gd.so

If the php7-mod-gd (opkg install php7-mod-gd) is installed, then the gd.so extension may be useful. It is related to graphics. And it isn't necessary to add that setting after the php7-mod-gd is installed, because when the package is installed it includes the /etc/php7/20_gd.ini file. The OpenWRT PHP binary / executable file is configured to automatically scan that directory for additional php module settings (-config-file-scan-dir=/etc/php7' is the included setting).

PHP Configuration for CGI

There are no specific settings for a "PHP CGI Service" as there are for the FastCGI PHP and PHP-FPM services. There are additional settings needed for Apache, Lighttpd, or Nginx to execute PHP scripts with their CGI capability (see below sections)

PHP FastCGI

The php7-mod-fastcgi is configured as a service named php7-fastcgi and configured in /etc/config/php7-fastcgi. There are only two settings. One that enables the service and the other that sets the listening port (port 1026).

PHP-FPM
Additional Information about CGI, FastCGI, and PHP-FPM

CGI (Common Gateway Interface), FastCGI (Fast Common Gateway Interface), and PHP-FPM are different methods that each of the web servers included with OpenWRT can handle PHP script files. CGI is the oldest, easisest to setup, and slowest (although in low load environments, it will suffice). FastCGI and PHP-FPM require additional software packages and configuration.

Below are a couple of websites that discuss the differences, advantages, etc. of each technolgy;

PHP for Apache
Installing and Configuring Apache for PHP using CGI

Configuration Files;

  • Apache: /etc/apache2/apache2.conf
  • Apache Optional: /etc/apache2/extra/WhatEverAdditionalFile.conf
  • PHP: /etc/php.ini and /etc/php7
  • PHP CGI: NONE

Service Commands;

  • service apache2 (stop / start / restart / reload)

Add and make sure the following settings exist in /etc/apache2/apache2.conf;

# When using PHP with "plain" CGI, the mpm_event_module must be disabled in favor of the mpm_prefork_module.  The mpm_event_module is utilized with php-fpm.
#LoadModule mpm_event_module lib/apache2/mod_mpm_event.so
LoadModule mpm_prefork_module lib/apache2/mod_mpm_prefork.so
LoadModule cgi_module lib/apache2/mod_cgi.so
LoadModule actions_module lib/apache2/mod_actions.so

ScriptAlias /php /usr/bin

# AddHandler application/x-httpd-php .php
# Choose / Uncomment either the above or below setting.  They are functionally equivalent.
# AddType application/x-httpd-php .php

Action application/x-httpd-php /php/php-cgi

The above configuration settings are not the only ones that should be present in the /etc/apache2/apache2.conf file. They are only related to PHP functionality with CGI and are in addition to a functional apache.conf file that contains <Directory> and <VirtualHost> Directives along with other settings that allow for static .htm or .html files made available by Apache.

Notes on PHP for Apache and CGI

The cgi_module is necessary for for Apache to utilize the PHP binary / executable php-cgi file (the program that makes PHP function).

In addition to the similar functionality it shares with the Alias Directive, the ScriptAlias Directive designates the directory alias as containing PHP files that will be handled by CGI.

As noted in the comments in the above Code Block, either the AddHandler or AddType Directive can be used to configure what Apache does with files that end with the .php extension. The AddHandler Directive, the "application/x-httpd-php" name is a lablel that is used in the Action Directive to associated it with a binary. Some examples use a trailing slash ( / ) and quotes ( " ), but after experimentation, the trailing / isn't necessary and as long as spaces aren't used in a path, quotes aren't needed either.

The guide at: https://openwrt.org/docs/guide-user/services/webserver/http.apache states the following should be put in the apache2.conf file, but was found to be unnecessary;

  <Directory "/usr/bin">
    AllowOverride None
    Options none
    Order allow,deny
    Allow from all
  </Directory>
PHP for Lighttpd
Installing and Configuring Lighttpd for PHP using CGI (see FastCGI below too)

The lighttpd, lighttpd-mod-cgi, php7, and php7-cgi packages should be installed as noted above in the Lighttpd and PHP Installation Sections.

Configuration Files;

  • Lightttpd: /etc/lighttpd/lighttpd.conf
  • Lighttpd CGI: /etc/lighttpd/conf.d/30-cgi.conf
  • PHP: /etc/php.ini and /etc/php7
  • PHP CGI: NONE

Service Commands;

  • service lighttpd (stop / start / restart)

Remember, the configuration file OpenWRT creates for CGI settings is /etc/lighttpd/conf.d/30-cgi.conf, not /etc/lighttpd/lighttpd.conf. It can be configured in the lighttpd.conf file, but to adhere to the OpenWRT convention it is recommended to place it in the 30-cgi.conf file.

Only the following lines are needed in the /etc/lighttpd/conf.d/30-cgi.conf ".php"  => "/usr/bin/php-cgi", see example below;

server.modules += ( "mod_cgi" )

cgi.assign                 = ( ".pl"  => "/usr/bin/perl",
                               ".cgi" => "/usr/bin/perl",
                               ".rb"  => "/usr/bin/ruby",
                               ".erb" => "/usr/bin/eruby",
                               ".php" => "/usr/bin/php-cgi",
                               ".py"  => "/usr/bin/python" )

The instructions also note the following setting be configured in the /etc/php.ini file, but it is already enabled by default in the OpenWRT php7 package: cgi.fix_pathinfo = 1

The remaining lines in the default configuration file are related to the default document directory chosen by OpenWRT for the Lighttpd installation. As recommended earlier, unless there are limited hardware resources available for a router, the location should be changed, thus negating the need for the additional settings.

Notes on PHP for Lighttpd and CGI

/usr/bin/php-cgi (with a bit of foreshadowing): The php-cgi binary / executable included with the php7-cgi OpenWRT package also includes FastCGI functionality. The php7-fastcgi package does not contain an additional binary. When installed, the php7-cgi package creates a symbolic link named /usr/bin/php-fcgi that points to the php-cgi file in the same directory. Additionally, a configuration file is inluded in /etc/config/php7-fastcgi package that enables FastCGI functionality. Type the following command to view the modules /usr/bin/php-cgi has available: php-cgi -m (this includes modules compiled in the php-cgi executable / binary file as well as added modules that are in separate files).

The instructions at https://openwrt.org/docs/guide-user/services/webserver/lamp#lighttpd1 indicate the above configuration is added to the /etc/lighttpd/lighttpd.conf file, but as noted, the /etc/lighttpd/conf.d/30-cgi.conf is the correct location for the AC Series of routers. If the instructions are followed it will cause a "Validation failed" error when starting the Lighttpd service because of two cgi.assign statements, as it is already present in the 30-cfi.conf file. It is possible the instructions are old or written for a different router platform, or the CGI configuration was separated and put into a different file at a later point.

Installing and Configuring Lighttpd for PHP using FastCGI

The lighttpd, lighttpd-mod-cgi, lighttpd-mod-fastcgi, php7, php7-cgi, and php7-fcgi packages should be installed as noted above in the Lighttpd and PHP Installation Sections.

Configuration Files;

  • Lightttpd: /etc/lighttpd/lighttpd.conf
  • Lighttpd FastCGI: /etc/lighttpd/conf.d/30-fastcgi.conf
  • PHP: /etc/php.ini and /etc/php7
  • PHP FastCGI: /etc/config/php7-fastcgi

Service Commands;

  • service lighttpd (stop / start / restart)
  • service php7-fastcgi (stop / start / restart)

Verify the following settings in the /etc/lighttpd/conf.d/30-fastcgi.conf file; and remove the comment hash tag (#) to enable them;

Code Block
fastcgi.server = ( ".php" =>

    # Be careful: lighty does *not* warn you if it doesn't know a specified option here (make sure you have no typos)
    ((
      #
      # To enable FastCGI PHP functionality, enable the below host and port settings (default port for FastCGI is 1026)
      #"host" => "127.0.0.1" ,
      #"port" => "1026" ,
      #
      #
      # To use FPM, disable the above host and port and enable either the port or socket method below (only one)
      #
      # Socket Method
      "socket" => "/var/run/php7-fpm.sock",                 # either socket or host+port
      #
      # Port Method (default port for PHP-FPM is 9000)
      #"host" => "127.0.0.1" ,
      #"port" => "9000" ,
      #
      # Which to use (Port or Socke)?
      # Research indicates there is less overhead associated with a socket.  A disadvantage for using a socket instead of a port is functionality is limited to a local server with some potential issues that occur with high usage situation.  A Port is also technically noted to be a type of socket with a disadvantage of slightly higher overhead and potential exhaustion of usable TCP ports.
      #
      #"bin-path" => "/usr/bin/php-fpm",    # optional 
      #"bin-environment" => <array>,         # optional 
      #"bin-copy-environment" => <array>,    # optional 
      #"mode" => <string>,                   # optional
      #"docroot" => <string> ,               # optional if "mode" is not "authorizer" 
      #"check-local" => <string>,            # optional
      #"max-procs" => <integer>,             # optional - when omitted, default is 4
      #"broken-scriptfilename" => <boolean>, # optional
      #"fix-root-scriptname" => <boolean>,   # optional, since 1.4.23 (option didn't work before 1.4.23)
      #"disable-time" => <integer>,          # optional
      #"allow-x-send-file" => <boolean>,     # optional, (deprecated since 1.4.40)
      #"x-sendfile" => <boolean>,            # optional, since 1.4.40
      #"x-sendfile-docroot" => <array>,      # optional, since 1.4.40
      #"kill-signal" => <integer>,           # optional, default is SIGTERM(15) (v1.4.14+)
      #3"tcp-fin-propagate" => <boolean>      # optional, propagate TCP FIN to backend (since 1.4.50) (default: disabled)
      ))
    )

fastcgi.map-extensions     = ( ".php3" => ".php",
                               ".php4" => ".php",
                               ".php5" => ".php",
                               ".phps" => ".php",
                               ".phtml" => ".php" )

The above example includes comments and settings related to PHP FPM (see below). And remember, most examples given by OpenWRT note the above settings in /etc/lighttpd/lighttpd.conf file, but that is not the case for the AC series of routers. An more detailed explanation of the above settings can be found here: https://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_ModFastCGI If additional FastCGI extensions other than .php, such as .php3, .php4, etc ensure the following items are configured in /etc/lighttpd/conf.d/30-fastcgi.conf;

Code Block
fastcgi.map-extensions     = ( ".php3" => ".php",
                               ".php4" => ".php",
                               ".php5" => ".php",
                               ".phps" => ".php",
                               ".phtml" => ".php" )

And finally, in order to ensure FastCGI is handling the PHP calls, disable or delete the /etc/lighttpd/conf.d/30-cgi.conf file.

Notes on PHP for Lighttpd and FastCGI

As noted above, if CGI (not FastCGI) is left enabled and everything is left in the default configuration order supplied by OpenWRT, the CGI interface will intercept PHP files before FastCGI. And as noted, the solution is to disable CGI (not really desireable) or change the order in the /etc/lighttpd/conf.d file by changing the name of the file from "30-cgi.conf" to "31-cgi.conf" so the settings in the "30-fastcgi.conf" file will take precidence. Why did OpenWRT not name it this way in the first place? Not sure, but it seems like it might be a good idea to change it at some point.

/usr/bin/php-cgi (with a bit of foreshadowing): The php-cgi binary / executable included with the php7-cgi OpenWRT package also includes FastCGI functionality. The php7-fastcgi package does not contain an additional binary. When installed, the php7-cgi package creates a symbolic link named /usr/bin/php-fcgi that points to the php-cgi file in the same directory. Additionally, a configuration file is inluded in /etc/config/php7-fastcgi package that enables FastCGI functionality. Type the following command to view the modules /usr/bin/php-cgi has available: php-cgi -m (this includes modules compiled in the php-cgi executable / binary file as well as added modules that are in separate files).

There does not seem to be a good way to verify whether CGI or FastCGI are handling PHP functionality for Lighttpd. Adding the single line of: <?php phpinfo(); ?> into a file named "info.php" will return an abundant amount of information including a line that states: Server API: CGI/FastCGI, whether using CGI or FastCGI, so it isn't very helpful. A method to confirm FastCGI is being used instead of CGI would be to disable or delete the /etc/lighttpd/conf.d/30-cgi.conf file.

Installing and Configuring Lighttpd for PHP using FPM (which relies on FastCGI)

The lighttpd, lighttpd-mod-cgi, lighttpd-mod-fastcgi, php7, php7-cgi, php7-fcgi, and php-fpm packages should be installed as noted above in the Lighttpd and PHP Installation Sections.

Configuration Files;

  • Lightttpd: /etc/lighttpd/lighttpd.conf
  • Lighttpd FastCGI: /etc/lighttpd/conf.d/30-fastcgi.conf
  • PHP: /etc/php.ini and /etc/php7
  • PHP FastCGI: /etc/config/php7-fastcgi
  • PHP FPM: /etc/config/php7-fpm, /etc/php7-fpm.conf, and /etc/php7-fpm.d

Service Commands;

  • service lighttpd (stop / start / restart)
  • service php7-fastcgi (stop / start / restart)
  • service php7-fpm (stop / start / restart)

Modify the settings in /etc/php7-fpm.d/www.conf as follows;

; A Port or Socket can be defined for the php7-fpm Service (only choose one)
; And remember to change the settings in the Lighttpd 30-fastcgi.conf file depending on which choice is made.
;
; Port
; listen = 127.0.0.1:9000
;
; Socket
listen = /var/run/php7-fpm.sock

; If the Socket method above is chosen, the following items must also be set, otherwise a "Permission denied socket" error will occur when the php7-fpm service is started.
listen.owner = http
listen.group = www-data
listen.mode = 0666

Do not make the mistake of using hash tags ( # ) for comments as they will prevent the php7-fpm service from running. Modify the settings in /etc/lighttpd/conf.d/30-fastcgi.conf noted in the above section as follows;

#"host" => "127.0.0.1" ,
#"port" => "1026" ,
"socket" => "/var/run/php7-fpm.sock",
Notes on PHP for Lighttpd and FPM (with FastCGI)

Make sure FastCGI is functioning correctly before FPM is added and configured. Adding the single line of: <?php phpinfo(); ?> into a file named "info.php" will now include useful information about what service is handling PHP requests: Server API: FPM/FastCGI

Additional Information about PHP with CGI VS PHP with FastCGI VS PHP with FPM can be found here;

Testing PHP Functionality

Create and save a PHP file (test.php) with this single line of code in it: <?php phpinfo(); ?>

PHP functionality can be tested with that file;

  • From a command line type the following: php-cgi /WhatEverPath/test.php
  • Place the file in a directory served by Apache (/usr/share/apache2/htdocs) and navigate to that file

As noted previously, but worth mentioning again, OpenWRT names the interactive command line interface for PHP php-cli. Most sites give examples that use the command php, so to make it easier create a symbolic link with this command: ln -s /usr/bin/php-cli /usr/bin/php

MariaDB Server

Installing
  • opkg update
  • opkg install mariadb-server mariadb-client libaprutil-dbd-mysql mariadb-server-extra mariadb-client-extra (dependencies are automatically installed)
  • Change the "option enabled '0'" to a '1' to enable in the /etc/config/mysqld file
  • Modify the following items in the /etc/mysql/50-server.cnf file;
    • Use the ARIA database engine instead of the default InnoDB to streamline RAM usage in the [mysqld] category of the file: default-storage-engine = aria (after finishing configuration, check at the MySQL command prompt with this command: SHOW ENGINES;
    • Move the database to an external eSATA drive: datadir        = /mnt/sdb3/mysql
    • Move the tmp directory to an external eSATA drive: datadir        = /tmp (This directory is relative to the datadir, in that it will be created at the same level as the mysql directory, so this is not an abolute path where it will utilize the /tmp directory in the root of the file system)
  • To create the default database: mysql_install_db --force --basedir=/usr
  • Start the service: service mysqldb start
  • To create a password for the current user (blank if not configured): /usr/bin/mysqladmin -u root password 'new-password'
  • Log into the command line for the database: mysql -u root -p or use phpMyAdmin see below
Optimizing for a Low Memory Footprint with the ARIA Engine

from: https://mariadb.com/kb/en/mariadb-memory-allocation/

Importing and Migrating Data from Other SQL Servers

To take advantage of the ARIA database engine, any databases imported should not have any information about engine="WhatEverDBengine". If they do, the database engine defined for each table will be used. If they do not have any information about which engine is assigned to a database, the default engine for the database server will be used. Use the below command to export a .sql database file (no method appears to be available with phpMyAdmin to export a database without the engine information included);

  • mysqldump -u root -p --skip-create-options WhatEverDatabaseName > WhatEverDatabaseFile.sql;
  • If using phpMyAdmin to import the database note the following
    • It is far slower and far more resource intensive (on the order of about 25 times) than using the command line to import a database.
    • For Apache web servers, when importing large databases, the TimeOut Directive should be set to a higher value to avoid a "Gateway Timeout" error. The default is 60 seconds.
    • This setting in the phpMyAdmin configuration file, config.inc.php, can be set too, but isn't necessary: $cfg['ExecTimeLimit'] = 3600;
    • Alternatively, use this command to import a database via the command line: mysql -u root -p WhatEverDatabaseName < /PathTo/DatabaseFile
General Information

Default database location: /mnt/data/mysql/ Default TEMP directory: /tmp Default database engine: InnoDB

Memory footprint..., Aria see https://coderwall.com/p/lz0qsa/convert-all-myisam-tables-to-aria, https://mariadb.com/kb/en/aria-storage-engine/, and the MariaDB Cookbook

Storage engines: innodb is the default, MyISAM is older, but has the smallest footprint, Aria seems to be the middle road (https://mariadb.com/kb/en/choosing-the-right-storage-engine/)

Show available storage engines: SHOW ENGINES\G or show engines;

phpMyAdmin

  • opkg update
  • opkg install php7-mod-mbstring php7-mod-json php7-mod-hash php7-mod-ctype php7-mod-zip php7-mod-gd php7-mod-mysqli php7-mod-session php7-mod-snmp zoneinfo-northamerica (if one is in North America, if not, choose another zone and remember, phpMyAdmin will display a blank page with no error if a zoneinfo-WhatEverZone is not installed in addition to the zoneinfo-core package, see additional information below, dependencies will also be installed automatically).

Make sure the /usr/share/apache2/htdocs/phpMyAdmin/tmp has 777 permissions, otherwise Apache based phpMyAdmin sites may stop responding: chmod 777 /usr/share/apache2/htdocs/phpMyAdmin/tmp

The following item is VERY important, hence it's typeface in BOLD CAPITAL letters. If the appropirate additional time zone module is not installed it can cause a completely invisible error (IE, no error in Apache, Lighttpd, or PHP logs). IE, it only displays a blank page. Even using a command line instance of PHP will not reveal the error. This line in the /phpMyAdmin/libraries/classes/Core.php file: date_default_timezone_set(@date_default_timezone_get()); is the source of the issue (Note, this is not the fault of phyMyAdmin, but it would be nice if they wrote a bit of code to address this situation). The error message that can be coaxed out of Lighttpd by taking that line of code and placing it in a file by itself is: Timezone database is corrupt – this should never happen! (thanks to this site for a key bit of information on that issue: https://e3fi389.wordpress.com/2014/12/07/timezone-database-is-corrupt-date-error-in-openwrt/)

  • ALSO MAKE SURE TO INSTALL THE APPROPRIATE TIME ZONE MODULE, IN ADDITION TO THE DEFAULT zoneinfo-core: opkg install zoneinfo-northamerica (for example)
  • To install all of the php7-mod packages if desired, but not necessary:opkg list | grep php7-mod-| awk '{print $1}' | xargs opkg install
  • wget https://files.phpmyadmin.net/phpMyAdmin/4.9.5/phpMyAdmin-4.9.5-english.tar.gz (or whatever the latest version is)
  • If not installed, wget needs: opkg install ca-certificates
  • tar -xzvf phpMyAdmin-4.9.5-english.tar.gz
  • mv WhatEverUnTarredDirectory /usr/share/apache/htdocs OR WhatEverLighttpd Directory
  • Change the permissions to what they should be, see CHOWN, etc. in the above Lighttpd section
  • Browse to: http://WhatEverURL/phpMyAdmin/setup/index.php, or use the below configuration file (/WhatEverPath/config.inc.php)
Code Block
<?php

/* Servers configuration */
$i = 0;

/* Server: WRT3200ACM [1] */
$i++;
$cfg['Servers'][$i]['verbose'] = 'WRT3200ACM';
$cfg['Servers'][$i]['host'] = '127.0.0.1';
$cfg['Servers'][$i]['port'] = '3306';
$cfg['Servers'][$i]['socket'] = '';
$cfg['Servers'][$i]['auth_type'] = 'cookie';
$cfg['Servers'][$i]['user'] = 'root';
$cfg['Servers'][$i]['password'] = 'WhatEverPassword';
$cfg['Servers'][$i]['MemoryLimit'] = '-1';

/* End of servers configuration */

$cfg['blowfish_secret'] = '\'ci.NDxXw@1QB^Y!x(`QY0<&e!|)XG`?';
$cfg['DefaultLang'] = 'en';
$cfg['ServerDefault'] = 1;
$cfg['UploadDir'] = '';
$cfg['SaveDir'] = '';
?>
  • The config.inc.php file permissions have to be set to whatever the web server is: chown apache:apache OR http:www-data config.inc.php (for Apache OR Lighttpd) and chmod 644 config.inc.php
  • REMEMBER: If using Lighttpd with PHP-FPM, restart the php7-fpm service as it does not automatically restart when Lighttpd is restarted (unless configured)
  • Also to remember to configure proper security for the phpMyAdmin within Apache or Lighttpd to restrict access to say only local IP Addresses.
  • It will also prompt to set up a phpMyAdmin table within the database, just click on the links and it will automatically create the database
  • Configure a TEMP folder for phpMyAdmin to use in the config.inc.php file: $cfg['TempDir'] = '/tmp/phpMyAdmin'; (as an example, make sure chmod 777 /tmp/phpMyAdmin, and to create the directory and set permissions when the router is rebooted in the rc.local file as everything in the /tmp directory will be deleted after a reboot of a router)
  • Also consider increasing php.ini settings for memory, upload, etc.
    • memory_limit = 100M
    • file_uploads = On
    • upload_max_filesize = 128M
    • post_max_size = 128M
    • max_file_uploads = 20
  • To diagnose any issues when attempting to access the phpMyAdmin setup this will display the error message (look for the line that says WarnMissingExtension to spot missing modules): php-cli /usr/share/apache2/htdocs/phpMyAdmin/setup/index.php
LetsEncrypt / ACME

opkg update

opkg install acme luci-app-acme

Additional Reading for OpenWRT and LAMP

A nice summary and comparison of CGI, FastCGI, and PHP-FPM: https://www.basezap.com/difference-php-cgi-php-fpm/

Other Software, Utilities, Drivers, & System Configuration, etc.

Package Installation with OPKG

opkg is the package management utility on OpenWRT.

Useful Utilities & Features

General Utilities

Superior text editor to VI: nano

TAR: For .tar files, BusyBox has a builtin tar command, however opkg install tar will install the full TAR suited allowing for extraction of many more types of .tar files beyond ones that are compressed with .gz / gunzip, including .xz among others.

Enhanced version of TOP (AKA Task Viewer): htop

GUI for Web Server (uHTTPd) that facilitates LuCI (the OpenWRT Web GUI): luci-app-uhttpd

"HTTPS capability" for WGET (WGET is installed by default but does not support HTTPS): libustream-mbedtls20150806 (or whatever current package name, or alterntively: opkg install libustream-mbedtls*, NOTE: the SSL version will not work)

For proper time zone detection by PHP and other scripts be sure to install whatever local time zone module is appropriate in addition to the core timezone software package (zoneinfo-core): zoneinfo-northamerica (as an example, there are other packages for the rest of the world)

To install all of the above noted utilities;

  • opkg update
  • opkg install htop restic luci-app-uhttpd libustream-mbedtls20150806 zoneinfo-northamerica

Full Versions of Commands available in BusyBox (but limited in BB due to size constraints)

  • opkg list coreutils*
  • opkg list shadow*
  • opkg list procps*

Additional commands are hidden in various other non-intuitive locations. If a desired command or utility isn't available, search for it by name in the LuCI GUI interface, System, Software, Filter Field and then install the package it is contained in. Use caution as some package names and descriptions are a bit misleading and may install undesired programs.

Alternate Shells

OpenWRT uses the ASH (put in CAPS to make it stand out, but technically correctly referred to as ash, same for bash / BASH) as the default shell within the BusyBox Binary / Executable. There are other choices. See the following two articles for an excellent explanation;

To install the chsh utility: opkg install shadow-chsh

Login

When logging into a command prompt via SSH, by default DropBear is the SSH / SSHD Server / Daemon that responds. Various things take place as configured in the /etc/init.d/dropbear file which also calls other scripts, including /lib/functions.sh and other scripts in the /lib/functions directory. A quick examination of the scripts seem to indicate the capacity to detect if a full version of BASH has been installed, but upon testing it doesn't work (if the functionality is there at all). To change the login shell, edit the /etc/passwd file (Caution: it is recommended to leave a shell open that will continue to use the old settings if something goes wrong when modifying the shell).

  • ASH: root:x:0:0:root:/root:/bin/ash
  • BASH: root:x:0:0:root:/root:/bin/bash
SHELLS File

The /etc/shells file contains a list of the various shells installed. By default, it contains a single line: /bin/ash

ASH (the BusyBox version of BASH (much smaller))

Both /bin/sh and /bin/ash redirect to /etc/busybox by default in OpenWRT.

Two main files are used to configure profile settings

  • /etc/profile: All user settings
  • /~/.profile (/root/.profile for the root user): individual user settings

Additional configuration documentation can be found here: https://linux.die.net/man/1/ash

BASH (the full version)

As noted, the default shell for OpenWRT is ASH. Check the /etc/passwd file for which shell the root user uses. For ASH, it will be /bin/ash, for BASH, it will be /bin/bash. Also try typing the env command, find the line in the output that states: SHELL=/bin/ash or /bin/bash

opkg install bash

Bash has several advantages, including keeping a history of commands that persists across reboots.

FISH
ZSH
Changing Shells

Install "Change Shell": opkg install shadow-chsh

List available shells: cat /etc/shells OR chsh -l (NOTE: The chsh -l command doesn't work in OpenWRT as it does in other Linux distributions because chsh was compiled without the -l option, presumably for space considerations)

Change shell: chsh -r /bin/bash (this will also allow history commands to persist too.)

Profiles

By default, all profiles are configured via the /etc/profile file. If multiple users are configured, each time a user logs into a command prompt, their profile will be configured with information in this file.

There are some indications that OpenWRT used /etc/scripts/misc/profile.sh as a method to configure profile environment variables about a decade ago.

Network Tools for Diagnostics

A tool to see all the ports a router is listening on: lsof -i -P -n | grep LISTEN (install the package with this command: opkg install lsof)

To see services listening on specific ports: netstat -lnp | grep WhatEverPortNumber

To install all of the above noted utilities;

  • opkg update
  • opkg install lsof

File Transfer Programs

SCP

Copy files between Linux machines using SCP, which in turn uses the SSH protocol (IE, nothing has to be installed on the client)

To copy from one router to another: scp -r /local/directory UserName@RemoteIPAddress:/remote/

WinSCP

A free Windows based program that enables easy Explorer like file transfers between a Windows Computer and a router via the SSH protocol (built into OpenWRT and enabled by default): https://winscp.net/eng/index.php

Note: SCP is not the fastest file transfer method, as it uses a copious CPU amount, but it is convenient. For large file transfers configure SAMBA (see below).

Samba Server and File Sharing

There are two versions of Samba Server available, 3.6.25 and 4.x.

  • opkg update
  • opkg install samba36-server OR opkg install samba4-server samba4-utils
  • opkg luci-app-samba OR opkg install luci-app-samba4
  • For additional Samba related tools: opkg install samba4-client samba4-admin samba4-utils
  • smbpasswd -a root (or whatever user is desired)

The stock OpenWRT Samba Server Configuration (in LuCI) can be replaced with something similar to below (LUCI GUI, Service, Network Shares, Edit Template Tab);

Code Block
[global]
        netbios name = OpenWRT
        server string = Samba on OpenWRT
        workgroup = WORKGROUP
        guest account = nobody
        security = user
        map to guest = Bad User
        guest ok = yes
        guest only = no
        timestamp logs = no
        preserve case = yes
        short preserve case = yes
        socket options = TCP_NODELAY SO_KEEPALIVE IPTOS_LOWDELAY SO_RCVBUF=65536 SO_SNDBUF=65536
        log level = 0
        syslog = 0
        passdb backend = smbpasswd
        smb encrypt = disabled
        smb passwd file = /etc/samba/smbpasswd

Below is the default OpenWRT configuration for Samba Server 3

Code Block
[global]
	netbios name = |NAME| 
	display charset = |CHARSET|
	interfaces = |INTERFACES|
	server string = |DESCRIPTION|
	unix charset = |CHARSET|
	workgroup = |WORKGROUP|
	bind interfaces only = yes
	deadtime = 30
	enable core files = no
	invalid users = root
	local master = no
	map to guest = Bad User
	max protocol = SMB2
	min receivefile size = 16384
	null passwords = yes
	passdb backend = smbpasswd
	security = user
	smb passwd file = /etc/samba/smbpasswd
	use sendfile = yes

A key to getting Samba 4 to work properly with Windows 10 is this: map to guest = Never The below is an actual functional smb.conf file for Samba 4 that works with Windows 10. Thanks to https://www.nodeum.io/howto/guest-access-in-smb2-disabled-by-default-in-windows-10 for the key piece of information. Click here for the default OpenWRT configuration for Samba 4.

Code Block
[global]
	netbios name = |NAME| 
	interfaces = |INTERFACES|
	server string = |DESCRIPTION|
	unix charset = |CHARSET|
	workgroup = |WORKGROUP|
        security = user
        timestamp logs = no
        preserve case = yes
        short preserve case = yes
        socket options = TCP_NODELAY SO_KEEPALIVE IPTOS_LOWDELAY SO_RCVBUF=65536 SO_SNDBUF=65536
        log level = 0
        syslog = 0
        passdb backend = smbpasswd
        smb passwd file = /etc/samba/smbpasswd
        # Below is the key to getting Samba Server to work with Windows 10
        map to guest = Never

There are so many different sources that babble about solving the Samba / Windows 10 issues that include ntlm = true, server min protocol = SMB3, min protocol = SMB3, blah, blah, blah. Nothing works. All of these items seem to be set correctly with default values as of a version of Samba sometime after 2019, so they do not fix the issue. For the "You can't access this shared folder because your organization's security policies block unauthenticated guest..." Error Message, the above noted map to guest = Never solves the issue. And whenever creating new shared directories, uncheck "Allow guests" (OpenWRT enables this by default).

Then dd a Network Share: In LUCI GUI, Service, Network Shares, General Settings or Edit Template Tab, enter a Name and a Path, the other defaults are fine.

If any attempts are made to edit the /etc/samba/smb.conf file directly, it will be overwritten each time by OpenWRT as that's the way it functions in OpenWRT. It can be prevented, but it is recommended not to do that in order to preserve the standard functionality of OpenWRT.

And lastly, remember if one attempts to share the "Root Directory" ( / ), none of the sub directories will open, because of the way the OpenWRT file system works.

WINS (Windows Internet Naming Service) for Samba

Invaluable Information from here: https://www.samba.org/samba/docs/using_samba/ch07.html (NOTE: This entire page is marked as "this is old information and might be incorrect", however, WINS is old too, and as it turns out, all of the information in regards to WINS is still accurate)

Samba Related Information


Samba Information

OpenWRT Samba is configured to look for the lmhosts file (all lower case) here: /etc/samba/lmhosts (it was verified by looking in the log files for where it loads the file)

To configure logging, add the following directives (minus comments) to the /etc/samba/smb.conf file in the [glolbal] section;

# The below is the default location
log file = /tmp/log/samba/samba.log
log level = 3
# Per log file, the below has been deprecated
# syslog = 1

Information from above was referenced from here: https://wiki.samba.org/index.php/Configuring_Logging_on_a_Samba_Server

Top Tips

Do NOT set the log level higher than 3 or it will just fill up with gibberish

Do NOT attempt to read the log file via a text editor through a Samba shared directory, or the log file will fill with recursive gibberish (IE, use nano or vi)

Best to not use these directives; client min protocol = SMB2, client max protocol = SMB3 (If SMB1 or SMB2 are needed, switch to Samba 3)

When configuring the Hostname in the LuCI GUI, System, System, General Settings Tab, use ONLY the host name, not the "fully qualified host name" (IE use OpenWRT, do not use OpenWRT.WhatEverDomain.WhatEverComOrLocalOrLanEtc)

Commands Related to WINS for Samba

nmblookup is the command that can be used to check information within the Samba WINS database.

Examples;

  • nmblookup WhatEverNameOfHost will display the IP Address information for that host.
  • nmblookup -S WhatEverWorkGroupName will display all the records*

* This webpage notes that there are various ways to display all of the records: https://superuser.com/questions/1492010/finding-all-samba-shares-in-local-network

Static Mappings for WINS (Static Entries for Host Names and IP Addresses) - Not to be confused with LMHOSTS File

As with everything in life (and OpenWRT), the solution isn't a simple 1, 2, 3 thing. The first item worth mentioning is that configuring an LMHOSTS file on an OpenWRT router will only work with name resolution queries run from the OpenWRT router. The LMHOSTS file will not be used when answering WINS queries from clients.

Adding Static Mappings is easy using the below method (and also useless, because the settings will disappear when the router is restarted). It assumes Samba 4 is being used, but will also work with Samba 3 if minor changes are made to the commands;

  • Stop the Samba Service (this also stops the NMBD service): service samba4 stop
  • Add an entry to the /var/lib/samba/wins.dat file using the following format (see wins.dat format explanation further down)
    • "NAME#TYPE" TTL ADDRESS+ FLAGS
  • Start the NMBD Service: service samba4 start

A better way to add Static Mappings that persist beyond router restarts is this;

  • Create and save a file named samba.static with entries in the below format in the /etc/samba/ directory: nano /etc/samba/samba.static (it can be any name, but make sure it's the same configured in the below script) (use whatever file editor you want, VI, etc.)
    • Put this line at the top of the file: VERSION 1 0
    • Enter subsequent entries on each line in this format: "NAME#TYPE" TTL ADDRESS+ FLAGS (see wins.dat format explanation further down)
  • Add the below commands to the OpenWRT Startup Scripts (via LuCI GUI: System, Startup, Local Startup Tab). The comments can be eliminated and are only included to describe what each command does;
######## Adds Static Mapping for WINS from /etc/samba/samba.static file to /tmp/lib/samba/wins.dat file ########

###### There is no need to stop or start the Samba Service because the OpenWRT StartUp Script (rc.d) has a start position of 95 and the Samba4 Service has a start position of 98, so the SMB service isn't even started when this script runs.  The samba4 stop and start lines were put in to note this because according to Samba documentation, the samba service must be stopped to modify the wins.dat file with static entries.
# /etc/init.d/samba4 stop

###### The samba directory and wins.dat file do not yet exist when these commands run during the startup process, so create them and make sure the permission are correct (the permissions should be correct, but explicitly make sure with the chmod command).
mkdir /tmp/lib/samba
touch /tmp/lib/samba/wins.dat
chmod 644 /tmp/lib/samba/wins.dat

###### Append Static Mappings (that the Microsoft term) for WINS in the samba.static file into the /tmp/lib/samba/wins.dat file that is dynamically updated by the SAMBA / NMBD Service, and also created if it doesn't already exist.  And as noted, wins.dat file will be deleted when the router is restarted).
cat /etc/samba/samba.static >> /tmp/lib/samba/wins.dat

###### /etc/init.d/samba4 start

wins.dat Format Explanation

  • "NAME#TYPE" TTL ADDRESS+ FLAGS
    • The quotes ( " " ) around NAME#TYPE are supposed to be there like that. Yes, it looks weird, but that's the format.
    • NAME = NetBIOS name of computer
    • TYPE = NetBIOS Type (00 = Workstation or Domain Name, 01 = Messenger (Workstation), 20 = File Server, etc.)
    • TTL = Time To Live in seconds, (Using a time of 0 (zero) ensures the entry will not be deleted by the Samba / NMBD service)
    • ADDRESS+ = One, possibly more addresses for the Computer / Entity. Only one is usually necessary for a computer or server, and testing wasn't done on this setting with multiple IP Addresses.
    • FLAGS = NetBIOS Flags (...from one of the below credited websites: The NetBIOS flags may be interpreted as additive hexadecimal values: 00 - Broadcast node registration, 20 - Peer node registration, 40 - Meta node registration, 60 - Hybrid node registration, 02 - Permanent name, 04 - Active name, 80 - Group name. The 'R' indicates this is a registration record. Thus 66R means: Hybrid node active and permanent NetBIOS name. These values may be found in the nameserv.h header file from the Samba source code repository. These are the values for the NB flags.
      • 64R = Hybrid Node Registration AND Active Name AND a "registration record"
  • Example: "BUBBA#00" 0 192.168.1.88 64R

The above information was sourced from these websites;

Other Thoughts on Static Mappings for WINS

While WINS might be old, it is still needed in many instances. For example, software that uses or was configured to use share names like "SERVER". How will that resolve to an IP Address? Broadcast? Yes, eventually. Unless Windows is configured to use DNS first (which it is by default) and there's a DNS server that resolves non-fully qualified host names to it's WAN IP Address by default (as BIND / NAMED does on OpenWRT and other versions of Linux installations). In cases as just described, a name like "SERVER" that is expected to resolve to a local IP Address, is instead resolved to a useless and inaccurate WAN IP Address. So WINS is still useful. Even if it is being used as a backstop for other poorly configured software. So be aware and understand what WINS can still be useful for.

The best tip (although incomplete) came from here (scroll down to Static WINS Entries): https://www.samba.org/~ab/output/htmldocs/Samba3-HOWTO/NetworkBrowsing.html. Tragically it was also buried in Google and Bing searches at an impossible to find depth. One suggestion for that website might be to use Microsoft's term: "static mappings" so it can be closer to the top in search results. After all the entire WINS thing was created by Microsoft.

/tmp/lib/samba/wins.dat (AKA /var/lib/samba/wins.dat)

/tmp/lib/samba/wins.tdb (AKA /var/lib/samba/wins.tdb)

/tmp/cache/samba/browse.dat (AKA /var/cache/samba/browse.dat)

Here's an interesting statement about the wins.dat file from https://wiki.rockstable.it/Samba: "On Samba the dynamically maintained database is stored persistently across reboots in /var/lib/samba/wins.dat, which is written in regular intervals." Keep in mind this was not written about OpenWRT. Does that make a difference? Yes it does. Look at the path OpenWRT stores the wins.dat file (Hint: It begins with /tmp, which means it does not persist across reboots). Is this compensated for with something in the /etc/init.d/samba4 configuration file? Nope. In the /etc/config/samba4 settings? Nope. Solution? Make one up.

In OpenWRT, is it possible to put manual entries in the /var/lib/samba/wins.dat file? Yes. Will the entry exist for more than about 30 seconds? No. So putting static entries into the wins.dat file is pointless. That's for the NMBD Service which responds to broadcast requests for a NetBIOS name.

The format of entries in the /var/lib/samba/wins.dat file are from here: https://www.linuxtopia.org/online_books/network_administration_guides/samba_reference_guide/17_NetworkBrowsing_23.html

  • "NAME#TYPE" TTL ADDRESS+ FLAGS
    • NAME = NetBIOS name
    • TYPE = NetBIOS Type (from https://www.techrepublic.com/article/how-netbios-name-resolution-really-works/, scroll down about half way and https://flylib.com/books/en/2.221.1/windows_internet_name_service_wins_.html): 00 = Workstation or Domain Name, 01 = Messenger (Workstation), 20 = File Server, etc.
    • TTL = Time To Live (in seconds), NOTE: Using a time of 0 (zero) makes the entry equivalent to a static entry.
    • ADDRESS+ = One, possibly more addresses for the Computer / Entity
    • FLAGS = NetBIOS Flags (from https://www.samba.org/~ab/output/htmldocs/Samba3-HOWTO/NetworkBrowsing.html): The NetBIOS flags may be interpreted as additive hexadecimal values: 00 - Broadcast node registration, 20 - Peer node registration, 40 - Meta node registration, 60 - Hybrid node registration, 02 - Permanent name, 04 - Active name, 80 - Group name. The 'R' indicates this is a registration record. Thus 66R means: Hybrid node active and permanent NetBIOS name. These values may be found in the nameserv.h header file from the Samba source code repository. These are the values for the NB flags.
      • 64R = Hybrid Node Registration AND Active Name AND registered

Wait! What about the /tmp/lib/samba/wins.tdb file? According to this (even though it refers to Samba 3, it applies to Samba 4): https://www.samba.org/samba/docs/old/Samba3-HOWTO/tdb.html, the wins.tdb file is used for "permanent storage" (IE static WINS entries). Can it be edited (in a useful manner)? No, because it is a binary file, not a text file. How is information input into it? Using the NET command? We'll see.

How about the TDBTOOL (It's like the MySQL Command, in that it opens it's own small interpreter environment)? More information here: https://www.samba.org/samba/docs/3.2/man-html/tdbtool.8.html Nope, that's a big rabbit hole that won't help much. Starting off with this;

  • tdbtool
  • open /var/lib/samba/wins.tbd
  • ...all the general "display" commands like LIST or DUMP, etc work
  • ...but a specific command, even a read only one like show WhatEverKey, doesn't work (and that's trying the KeyName and the KeyName followed by all the periods)

Ahhh! Here's the answer, with the best tip coming from this site: https://samba.samba.narkive.com/UPIyT5mM/samba-as-a-wins-server But alone that isn't enough as the static entries need to be made so they can persist across router reboots.

  • Stop the NMBD Service (Hint: the SMB service starts and stops the NMBD service in OpenWRT): service samba4 stop (assuming Samba 4 is being used, which it should be, but plain samba, AKA Samba 3 should work the same.)
  • Add an entry to the /var/lib/samba/wins.dat file (...remembering that it will not persist across router reboots, see below to solve that issue)
  • Start the NMBD Service: service samba4 start
  • Add the below to the OpenWRT Startup Scripts (via LuCI GUI: System, Startup, Local Startup Tab;
### Adds Static Mapping for WINS from /etc/samba/samba.static
### Don't forget to put static entries in the above noted file in the correct format

###### There is no need to stop or start the Samba Service because the OpenWRT StartUp Script (rc.d) has a start position of 95 and the Samba4 Service has a start position of 98, so the SMB service isn't even started when this script runs.  The samba4 stop and start lines were put in to emphasize this because according to Samba documentation, the samba service must be stopped to modify the wins.dat file with static entries.
###### /etc/init.d/samba4 stop
###### The samba directory and wins.dat file do not exist when this script runs, so create them and make sure the permission are correct (they should be, but make sure with the chmod command).
mkdir /tmp/lib/samba
touch /tmp/lib/samba/wins.dat
chmod 644 /tmp/lib/samba/wins.dat
###### Put any static mappings (that the Microsoft term) for WINS in the samba.static file
cat /etc/samba/samba.static >> /tmp/lib/samba/wins.dat
###### /etc/init.d/samba4 start


Recommendation for Windows Hosts that are Multihomed (IE, have more than one network interface)

For some odd reason, if only one interface is configured with WINS server information, it reports the IP Address of all the network interfaces on the Windows machine to the WINS Server. IE, all the other network interfaces can have a blank / empty entry for WINS server, but that one network interface configured with a WINS server will report all of the IP Addresses associated with all of the other network interface. To prevent this, configure a different WINS server for each interface OR "Disable NetBIOS over TCP/IP" (oddly, this does not disable the ability of one to access shared folders, incoming or outgoing, on the network interface in question as it seems NetBEUI is the acronym that encompasses that functionality). This even includes PPTP VPN Connections and probably OpenVPN connections too.

Deprecated Configuration Directives from Samba3 to Samba4

There are several configuration directives that have been removed / deprecated from Samba 4. They include "announce as", "announce version", along with some others.

Other Information
  • If there is no Windows Domain Controller within a subnet, the following configuration is recommended for the /etc/dhcpd;
# This configures Samba to enable WINS support
wins support = yes
# The following settings will make the WINS functionality of Samba the main "Browser" for a subnet
# If using with a Windows Domain infrastructure, probably best to research a bit more before doing the following;
local master = yes
os level = 255
preferred master = yes
domain master = yes
  • The netbios name = |NAME| directive in Services, Network Share, Edit Template Tab in the OpenWRT GUI configures SAMBA with the name defined in the System, System, Hostname Field.

Remaining Items to Document

POPTOP / PPTPD

First a warning so readers don't get frustrated: Out of the box (as in a virgin installation of the POPTOP / PPTPD Package), the configuration for PPTPD from OpenWRT as of 8.2020 is broken and will not function. Credit and thanks to this web site for a hint on correcting the default configuration was found here: https://forum.openwrt.org/t/default-config-file-for-pptpd-lacks-logwtmp-option/4795 How to fix it? Well, follow the below directions. Hint: The key is setting the option 'logwtmp' '0' directive in the /etc/config/pptpd file (see below for more information).

And yes, for all the haters out there, PPTP is essentially broken as of 2021 and nobody is planning on fixing it or updating anything, so use OpenVPN to be secure. But... It is still useful to have this as a backup method of access to a router. Plus the firewall can be configured such that the PPTP ports are only open to certain IP Addresses. And given that we live in a world where the weakest link in any system is the human being, not technology, it's OK to have PPTP available if one needs it. So to all the nay sayers: Shhhhhhh.

Installation

See the PPTP for Clients a couple of sub sectins below and make sure the package (opkg install kmod-nf-nathelper-extra) for that is installed and configured (read in the PPTP Client Section above) too. The client software may or may not be necessary for the Server service to work.

opkg install pptpd ppp (dependencies will automatically be installed if just pptpd is installed)

There is no LuCI GUI available. Given there is no LuCI GUI it is a bit odd the configuration of PPTPD is done through an /etc/config/ppptd file, which is usually reserved for services that have a companion LuCI GUI available. There is a dependency package named luci-proto-ppp that gets installed, but there doesn't seem to be any GUI interface other than maybe something in the System, Realtime Graphs section of the LuCI GUI for PPP traffic (and that's just speculation) .

POPTOP / PPTPD Configuration Files and other Related File Locations

  • OpenWRT PPTPD Configuration File (Hint: Make use of this one, even though there is no LuCI GUI interface, see information later in this section): /etc/config/pptpd
  • PPTPD Configuration File: /etc/pptpd.conf* (BIG Asterisk here, see below) (as part of the /etc/init.d/pptpd startup script, this file is copied to /var/etc/pptpd.conf. This could be changed in the startup script, but to keep things withing the OpenWRT configuration paradigm things can be left as they are, but just know this is going on behind the scenes.)
  • PPP Configuration Files: /etc/ppp
    • /etc/ppp/chap-secrets (AKA User Names and Passwords for PPTPD): /etc/ppp/chap-secrets (the /etc/ppp/chap-secrets is actually "located" here /tmp/etc/chap-secrets and is dynamically generated by the /etc/init.d/pptpd startup script. When PPTPD is started a symbolic link is created as /etc/ppp/chapt-secrets which is pointed to /tmp/etc/chap-secrets. It should also be noted the pptpd package contains an /etc/ppp/chap-secrets file that is empty except for some commented out column headings. This might lead one to believe that this is the file where user names and passwords are created for PPTPD. This is not the case. The user names and passwords are dynamicaly generated as previously noted and the information used when it is generated is derived from the /etc/config/ppptp file. So make sure user names and passwords are created in the /etc/config/pptpd file in the format noted in the example below)
    • /etc/ppp/filter (OpenWRT PPTPD doesn't seem to utilize the settings in this file, even though it is included, so probably relegated to PPP only stuff. Research indicates it seems to be related to "allowed" outbound protocols)
    • /etc/ppp/options (This file contains the ppp (Point to Point Protocol) configuration and can be left with default settings. Do not confuse it with the options.pptpd file which is used for PPTPD PPP settings. IE, PPP is used for more than PPTPD and the plain options file is just for PPP)
    • /etc/ppp/options.pptpd (this file is copied to /var/etc/options.pptpd in the /etc/init.d/pptpd startup script)
    • /etc/ppp/resolv.conf (this file isn't necessary for PPTPD to function, but can be used for DNS name resolution.) (The /etc/ppp/resolv.conf file is also a symbolic link pointing to /tmp/resolv.conf.ppp, which is created by other OpenWRT services.)

Configuring PPTPD

Again a reminder that there is no LuCI GUI for PPTP (maybe there once was, but not likely to see one in the future). But it's still better to configure things within the confines of the OpenWRT system.

First, configure the /etc/config/pptpd file. Below is a working example;

config service 'pptpd'
	option 'enabled' '1'
	option 'logwtmp' '0'

config 'login'
	option 'username' 'WhatEverUserName'
	option 'password' 'WhatEverPassword'

config 'login'
	option 'username' 'AnotherUserNameETC'
	option 'password' 'AnotherPaswordETC'

Notice the option 'logwtmp' '0' line. It MUST be included for the service to start (or the startup script in /etc/init.d/pptpd has to be modified). And of course substitute the W.X.Y.Z and ABC with your own IP Address range.

The above noted "logwtmp" setting is NOT included in the default pptpd file. That is very, very odd, because the /etc/init.d/pptpd startup script explicilty checks for the existence of that setting and will show an "sh: out of range" error message if it is not included. So why would the default startup script requre a setting that isn't included in the default configuration file? Additionally the main OpenWRT documentation page for PPTPD does not mention it at all. It's almost like the nice people at OpenWRT don't want PPTPD to be used. It is a somewhat "old & busted" VPN protocol (Google it), so using a more modern alternative like OpenVPN would be a good choice. But sometimes it is necessary to support older protocols such as this.

From there everything gets better. The following files can be manually configured and the PPTPD startup script copies them to the /var/etc directory for the service to use when it starts up;

  • /etc/pptpd.conf (see below for a working version of this file, slightly different than the default OpenWRT version)
  • /etc/ppp/options (this can be left with default OpenWRT settings)
  • /etc/ppp/options.pptpd (see below for a working version of this file, slightly different than the default OpenWRT version)
  • /etc/ppp/chap-secrets: This is actually a symbolic link to /var/etc/chap-secrets, and that file is in turn dynamically generated from the information in /etc/config/pptp

Below is a working example of the /etc/pptpd.conf file;

#debug
#speed 115200
#stimeout 10
#localip & remoteip are not needed, ip management is done by pppd

# The above lines are the default OpenWRT settings for /etc/pptpd.conf.  The last comment is not very accurate.
# Translating the above geek talk, look in /etc/ppp for the options.pptpd file for additional options.

# The Webmin PPTP VPN Server Module stores information here in this file, /etc/pptpd.conf

# The below option setting may be redundant as it is included in the /etc/init.d/pptpd startup script in OpenWRT
# But for the sake of including it so it is displayed within the Webmin interface, it is included here.

option	/etc/ppp/options.pptpd
pid-file /var/run/pptpd.pid
connections 5

# If using just the /etc/config/pptpd method to configure PPTPD, then the below two items are not necessary
# However, if the PPTPD Webmin Module is being used, those settings should be included here.
localip	W.X.Y.Z
remoteip W.X.Y.Z

# Also, if Webmin is being used, the redundant information above should be removed from the /etc/config/pptpd file

Below is a working example of the /etc/ppp/options.pptpd file;

logfile /var/log/pptp-server.log

proxyarp
lock
refuse-chap
refuse-mschap
refuse-eap
refuse-pap
require-mschap-v2

ms-dns W.X.Y.Z
ms-wins W.X.Y.Z

# This option is NOT supported by the OpenWRT PPTPD
# require-mppe-128

# Name of the local system for authentication purposes 
# (must match the second field in /etc/ppp/chap-secrets entries)
# The default OpenWRT PPTPD name used in the autogenerated chap-secrets file is pptp-server 
name pptp-server


### Additional settings from the Original OpenWRT configuration file shown here as disabled

## lcp-echo-failure 3
## lcp-echo-interval 60
## default-asyncmap
## mtu 1482
## mru 1482
## nobsdcomp
## nodeflate

And for both of the above examples, include your own IP Addres information where W.X.Y.Z is noted.

Don't for get to configure firewall settings such that it allows PPTP connections from the internet. After all, that's what it is for. Below are the settings to include in the /etc/config/firewall file or to configure within the LuCI GUI, Network, Firewall, Traffic Rules Tab;

config rule
	option dest_port '1723'
	option src 'wan'
	option name 'PPTP'
	list dest_ip 'W.X.Y.Z'
	list dest_ip 'W.X.Y.Z'
	option target 'ACCEPT'
	option family 'ipv4'
	option proto 'tcp'

config rule
	option target 'ACCEPT'
	option name 'GRE for PPTP'
	option src 'wan'
	option proto '47'

# ...and while you're in here add the below to the CONFIG ZONE named 'lan' (more information in the next section)

	list device 'ppp+'

The above list dest_ip 'W.X.Y.Z' are only needed if using MWAN3 and can be eliminated from firewall configurations that don't have to consider multiple WAN ports. If configured it would be set to the WAN IP Addresses of the router. Also in the /etc/config/firewall file is a setting that needs to be added to the 'lan' zone;

list device 'ppp+'

OR

option device 'ppp+'

...below is an example of a complete 'lan' zone as it is usually configure within OpenWRT with the 'ppp+' setting at the end;

config zone 'lan'
	option name 'lan'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'ACCEPT'
	option family 'ipv4'
	option network 'lan'
	list device 'ppp+'

The above list device 'ppp+' directive is needed for proper routing between remote clients and the router's local subnet.

See here for some additional documentation on /etc/config/firewall settings: https://openwrt.org/docs/guide-user/firewall/firewall_configuration

And one last thing to configure are couple of things the startup / shutdown script does not do.

  • It does not delete / clean up the /var/run/pptpd.pid file
  • It does not delete the /etc/var/chap-secrets file that is generated. The interesting fallout from this is that every time the PPTPD service is stopped an started, it appends the information in the 'login' section of the /etc/config/pptpd file to /var/etc/chap-secrets. If there are several user names and the service is restarted a couple of times, the number of redundant logins increases quite quickly.

Insert the following code into the /etc/init.d/pptpd file to correct those issuea;

stop_service() {
	rm /var/run/pptpd.pid
	rm /var/etc/chap-secrets
}

Please note, that if the service is ever upgraded, that bit of code will need to be reinserted. But given that the PoPtOp Daemon hasn't been updated since October of 2013, there probably aren't additional updates on the horizon (https://sourceforge.net/projects/poptop/files/pptpd/pptpd-1.4.0/).

Additional Information

The information on the OpenWRT site on PPTP is a bit misleading (possibly just outdated), because as noted above /etc/pptpd.conf is not the true configuration file. It is actually generated dynamically as many OpenWRT services are. The article also references an issue with the /etc/init.d/pptpd startup script that no longer seems to exist.

This option for the /etc/ppp/options.pptpd is NOT supported by the OpenWRT PPTPD service: require-mppe-128 (an error message of: In file /var/etc/options.pptpd: unrecognized option 'require-mppe-128' error will occur if it is included). It should also be noted that the mppe-128 is built into the OpenWRT /usr/sbin/pptpd binary / executable file, thus making the setting unneccessary as it is enabled by default (pptp-server.log if enabled shows this: MPPE 128-bit stateless compression enabled). So do not include require-mppe-128 in the /etc/ppp/options.pptpd.

And finally, just because the example given in the OpenWRT tuturoial, is so convoluted and opaqe, is their example (from here: https://openwrt.org/docs/guide-user/services/vpn/pptp/server) explained;

uci rename firewall.@zone[0]="lan" <-- Rename the first zone in the /etc/config/firewall file as 'lan'

uci rename firewall.@zone[1]="wan" <-- Rename the second zone in the /etc/config/firewall file as 'lan'

uci del_list firewall.lan.device="ppp+" <-- Delete the list device 'ppp+' directive in the 'lan' zone of the /etc/config/firewall file

uci add_list firewall.lan.device="ppp+" <-- Add that same directive back to the same spot (no it doesn't seem to make much sense to deleted it above, but adding it is a good choice if it isn't there already)

uci -q delete firewall.pptp <-- Delete any zone titled pptp in the /etc/config/firewall file (maybe to make sure there aren't any incorrect legacy settings, but this assumes the zone is named 'pptp' and won't help if it is named differently

uci set firewall.pptp="rule" <-- Create a new rule with the below settings;
uci set firewall.pptp.name="Allow-PPTP"
uci set firewall.pptp.src="wan"
uci set firewall.pptp.dest_port="1723"
uci set firewall.pptp.proto="tcp"
uci set firewall.pptp.target="ACCEPT"
uci commit firewall

Hint: The same settings can be configured with far fewer keystrokes by simply editing the /etc/config/firewall file. The example could also be made far more cleary by directly editing the /etc/config/firewall file, instead of blindly entering a bunch of command, some of which are useless. Additionaly, some won't work correctly if the 'lan' and 'wan' zones aren't at index 0, and 1, as they are by default (IE, if someone has manually added additional zones).

PPTP (Point to Point Tunneling Protocol) for Clients (IE Clients behind the Router using a remote PPTP system)

Again, to be clear, this section is not about getting PPTP / POPTOP service / daemon working on a router. This section is about a router allowing PPTP connections to pass through it.

OpenWRT defines the use of PPTP Clients on the LAN side of a router that wish to connect to a PPTP server via the internet as NAT traversal for PPTP. Default installations of OpenWRT do not have the capability to facilitate PPTP connections by clients (IE, computers on the LAN side of the router). The following software package must be installed;

  • opkg update
  • opkg install kmod-nf-nathelper-extra

The instructions on enabling the capability is a bit lacking on the OpenWRT site, so below is an improved explanation. After installing the above package, do the following;

  • Create a file named 20-nf-conntrack-helper.conf in /etc/sysctl.d: nano /etc/sysctl.d/20n-nf-conntrack-helper.conf
  • Add a single line of code in the 20-nf-conntrack-helper.conf file to enable the program: net.netfilter.nf_conntrack_helper = 1
  • Save the file: CTRL + O, then exit nano: CTRL + X
  • Restart the sysctl service: service sysctl restart

PPTP should now work for clients wishing to use PPTP connections.

As has been mentioned and will continue to be mentioned, it is understandable that the OpenWRT documentation may be lacking in some ways. Creating and writing good documentation is difficult and time consuming. The nice people responsible for OpenWRT spend most of their time making things work, improving functionality, adding new firmware for new routers, etc.. This leaves little time for good documentation. So for all the nice people that work so hard on OpenWRT, thank you. And no offense meant. The rather cryptic several lines written by the author of the below noted article for more information very likely uses that "shortcut" to create files or may have thought it was helpful to present it in that way. And it may work for some people. But it was decided to present it here slightly differently as done above.

More information on enabling the feature can be found here: https://openwrt.org/docs/guide-user/services/vpn/pptp/nat_traversal

OpenVPN

This section is written for people that are experienced with OpenVPN.

REMEMBER (It will make sense later, and is worth pointing out at the beginning):Certificates are a requirement of encrypted communication for OpenVPN. That part of OpenVPN is made possible by OpenSSL. Two things to remember are these;

  • The /etc/openvpn/openvpn-ssl.cnf file contains a major flaw as it delivered by OpenWRT in the software package. There is a directive line (default_md    = md5) that will not work with the version of OpenVPN provided by OpenWRT (it's actually been that way for several versions. The directive instructs OpenSSL to produce certificates using a method that has been deemed comprimised. The line should instead read: default_md    = sha256
  • There's also a frustrating issue that comes up with a newly created certificate that won't work until the next day. Solution? Set the time of the router to a day or so in the past. Now that can be an adventure because it can't be done via the LuCI GUI. It can of course be done via the command line or Webmin.

The LuCI interface provides a nice interface for keeping track of OpenVPN Server and Client configuration, plus editing and enabling and disabling a specific Server or Client configuration file. OpenVPN for OpenWRT operates as it did for CentOS 6 where a single "OpenVPN Service" would "spawn" multiple instances of the OpenVPN binary / executable depending on how many Server and Client configuration files there are. CentOS 7 and newer has it configured such that each instance of an OpenVPN Server and / or Client configuration file requires a separate service.

Installation

  • opkg update
  • opkg install openvpn-easy-rsa openvpn-openssl (Any dependencies will automatically be installed, also see Notes section below)
  • Install the LuCI GUI interface for OpenVPN manually (see note below on the LuCI, System, Software installation for the OpenVPN LuCI GUI below)
    • opkg download luci-app-openvpn
    • opkg install WhatEverTheFileNameThatGetsDownloaded

Files & Directories

  • /etc/config/openvpn: File for OpenVPN connections configured within the LuCI GUI interface AND "includes" for additional OpenVPN configuration files
  • /etc/openvpn: Directory for storing all other OpenVPN settings and OpenSSL settings related to OpenVPN
  • /etc/openvpn/keys: Common directory name for storing OpenVPN certificates. Manually create.
  • /etc/openvpn/ccd: Common directory name for storing OpenVPN client configuration settings. Manually create.
  • /etc/openvpn/client: Unused by the OpenWRT version of OpenVPN, sometimes used with other Linux distributions (CentOS, etc.). It is recommended to store all Server and Client configuration files in /etc/openvpn as that is the only directory scanned by the /etc/init.d/openvpn OpenVPN Service startup script.
  • /etc/openvpn/server: Unused by the OpenWRT version of OpenVPN, sometimes used with other Linux distributions (CentOS, etc.). It is recommended to store all Server and Client configuration files in /etc/openvpn as that is the only directory scanned by the /etc/init.d/openvpn OpenVPN Service startup script.
  • etc/openvpn/openvpn-ssl.cnf: Common configuration file name for OpenSSL settings when creating certificates for OpenVPN

Configuration

OpenWRT LuCI Configuration File (/etc/config/openvpn) for a single OpenVPN Service instance;

config openvpn 'Server'
	option config '/etc/openvpn/Server.conf'
	option enabled '1'

The LuCI GUI can be used in a myriad of ways. The most basic of which is to manage OpenVPN configuration files that are created in a text editor.

Working example of an OpenVPN Server configuration file (not to be confused with the OpenWRT Luci configuration file, see above);

#If more than one WAN then use multihome directive
#multihome
dev tun2
topology subnet
push "topology subnet"
mode server
ifconfig W.X.Y.Z 255.255.255.0
ifconfig-pool W.X.Y.100 W.X.Y.199 255.255.255.0
route-gateway W.X.Y.Z
push "route-gateway W.X.Y.Z"
port 1194
proto udp
verb 3
route W.X.Y.Z 255.255.255.0
#Can be handled in CCD files
#push "route 192.168.1.0 255.255.255.0"
client-config-dir ccd
client-to-client
tls-server
keepalive 15 120
ca /etc/openvpn/keys/WhatEverPath/ca.crt
cert /etc/openvpn/keys/WhatEverPathserver/WhatEverCrt.crt
key /etc/openvpn/keys/WhatEverPath/WhatEverKey.key
dh /etc/openvpn/keys/WhatEverPath/dh2048.pem

In the above configuration file, it is assumed that keys have already been generated (see below section for using Webmin to generate certificates). The above storage location for keys is just an example that can be customized to any directory.

PID File (if needed)

If there's a situation where a PID file is needed to keep track of OpenVPN functionality, thankfully OpenWRT has not included that in their init.d configuration. But it can be added. Below is what needs to be added to the /etc/init.d/openvpn file;

...in the "openvpn_add_instance" section, add the line in between --->  <----.  The rest of the surrounding code for that single line is already there and is just put here for reference.  An obviously don't include the ---> or <--- "arrows";

openvpn_add_instance() {
	local name="$1"
	local dir="$2"
	local conf="$3"

	procd_open_instance "$name"
	procd_set_param command "$PROG"	\
		--syslog "openvpn($name)" \
		--status "/var/run/openvpn.$name.status" \
		--cd "$dir" \
		--->     --writepid "/var/run/openvpn.$name.pid" \    <----
		--config "$conf"
	procd_set_param file "$dir/$conf"
	procd_set_param term_timeout 15
	procd_set_param respawn
	procd_append_param respawn 3600
	procd_append_param respawn 5
	procd_append_param respawn -1
	procd_close_instance
}



...and at the bottom of the file, add the following (it removes the PID file after the OpenVPN service / daemon is stopped;

stop_service()
	{
	rm /var/run/openvpn.*
	}
Firewall

And don't forget to open up the appropriate ports on the firewall;

  • Use the LuCI GUI, Network, Firewall, Traffic Rules Interface to configure

OR

  • Edit the /etc/config/firewall File

The standard OpenVPN Server Port is 1194 UDP

Network

...this section not complete (among others)

/etc/config/firewall;

config zone

   option name 'OpenVPN'

   option input 'ACCEPT'

   option forward 'ACCEPT'

   option output 'ACCEPT'

   option network 'TUN002 TUN1'

config rule

   option dest_port '1194'

   option src 'wan'

   option name 'OpenVPN_TCP_UDP_1194_WRT1900ACS'

   list dest_ip ''

   option target 'ACCEPT'

   option family 'ipv4'

   list proto 'tcp'

   list proto 'udp'

config forwarding

   option dest 'OpenVPN'

   option src 'lan'

config forwarding

   option dest 'lan'

   option src 'OpenVPN'

config forwarding

   option dest 'lan'

   option src 'wan'

/etc/config/network

config interface 'TUN1'

   option ifname 'tun1'

   option proto 'static'

   option ipaddr 'W.X.Y.Z'

   option netmask '255.255.255.0'

Certificate Management for OpenVPN with Webmin (see Webmin Section below)

First the reminders;

  • Do NOT use Webmin for OpenVPN settings. Instead use the LuCI GUI and / or edit text files (starting and stopping the service is fine)
  • ONLY use it for Certificate management for OpenVPN.
  • Watch out when clicking the "Keys list" link as it is very close to the Remove link. If the Remove link is clicked, there is no confirmation about deleting the entire Certificate infrastructure.
Configuring a Certificate Authority Infrastructure (Certificate Authority, Server Certificate, Client Certificate(s)

For some odd reason (possibly troubleshooting), it is possible to create an OpenVPN infrastructure that transmits information without encryption. That's a bit too "open". In order to encrypt communication one must create a "Certificate Infrastructure". This includes first, a Certificate Authority (CA), then a certificate for a Server, then certificate(s) for clients.

There are many tutorials on this, all of them use the command line. Webmin makes it very easy to do and keep track of certificates. Even with that capability, keeping things in an organized structure is important. This includes naming conventions. A CA could be named Mary Poppins. But that isn't very helpful as a name for a CA if others are involved in managing an infrastructure.

If the Webmin module is configured as noted below, the entire certificate infrastructure (minus OpenSSL settings) will be stored in /etc/openvpn/keys

  • Create a Certificate Authority
Tips
  • Change the date before configuring any CA infrastructure or Certificate to at least the previous day as sometimes a frustrating problem occurs where the created certificate is not yet valid.
  • Routers with Multiple WAN Ports
    • For any OpenVPN Server File, use this directive: multihome (research it or Google it)
  • Had a "magic / matrix" moment happen when installing the LuCI GUI for OpenVPN. OpenWRT instead downloaded the .ipk file and saved it in the /etc/init.d directory. That messed up all the init.d scripts after that

Webmin for OpenVPN and Certificate Management

Only some features of the Webmin Module are useful. First and foremost is the Certificate management. Works great. As noted above, watch out when clicking the "Keys list" link as it is very close to the Remove link. If the Remove link is clicked, there is no confirmation about deleting the entire Certificate infrastructure. Bad design, oh, well.

Between the LuCI GUI and Certificate Management portion of Webmin, all aspects of OpenVPN can be conveniently controlled via a GUI interface.

The log display doesn't work properly, even when log files are configured properly.

Editing and managment of the OpenVPN service

The Webmin module for OpenVPN & Certificate management is not a "standard module".

  • Install in the Webmin interface: Webmin, Webmin Configuration, Webmin Modules, Install from Local File, Select File, Install Module.
  • By default, the OpenVPN... Module is located in Servers. Given that it deals with Networking and an equivalent Module (PPTP) is located in Networking, it makes sense to relocate the Module to Networking
    • Webmin, Webmin Configuration, Reassign Modules, OpenVPN..., Networking, Save

Below is a working configuration file for the OpenVPN & Certificate Authority Module (/etc/webmin/openvpn/config)

openvpn_path=/usr/sbin/openvpn
br_start_cmd=
openssl_version=1.1.1g
default_server=
br_end_cmd=
zip_cmd=/usr/bin/gzip
openssl_home=/etc/openvpn/openvpn-ssl.cnf
tail_cmd=
openvpn_pid_path=/var/run
log_refresh=
status_cmd=
start_cmd=/etc/init.d/openvpn start
openvpn_version=2.4.7
openvpn_clients_subdir=client
down_root_plugin=
openssl_path=/usr/bin/openssl
openvpn_pid_prefix=openvpn
openvpn_keys_subdir=keys
openvpn_home=/etc/openvpn
log_lines=9999
stop_cmd=/etc/init.d/openvpn stop
openvpn_servers_subdir=server

Notes

  • Use the OpenSSL version of OpenVPN (openvpn-openssl), not the mbedTLS (openvpn-mbedtls), and definately not openvpn-nossl (there is no security, but possibly good for testing configuration files). See here for additional information
  • If the /etc/config/openvpn file contains any sort of syntax error (if the file has been modified in a text editor for example), the configuration file will upload, but it will not be displayed as available in the LuCI OpenVPN GUI.
  • There's a bit of an issue with the OpenVPN LuCI interface when using the OVPN configuration file upload. When the Browse button is clicked, the initial "Choose File to Upload" dialogue selects .ovpn as the default file extension. This might lead one to believe that any files uploaded should have a file name that ends in .ovpn. This is not the case. A quick inspection of the /etc/init.d/openvpn file for the OpenVPN service reveals that it scans for files ending in .conf. So make sure any files uploaded via the LuCI GUI interface for OpenVPN end in .conf.
  • The /etc/openvpn Directory contains two sub-directories: client and server. These are default OpenVPN directories, but it also implies that Server and Client configuration files should be placed in these directories. This is not the case. An examination of the /etc/init.d/openvpn OpenVPN configuration file revealse that it only scans the /etc/openvpn Directory for configuration files. Additionally, the LuCI GUI interface for OpenVPN places the files in /etc/openvpn and does not scan the sever and client sub-directories for additional configuration files.
  • As of 8.2020, there is also an issue with the version number of of the LuCI GUI for OpenVPN (luci-app-openvpn). The package version displayed via the System, Software page in the LuCI GUI displays git-2.229... Downloading the IPK file manually (opkg download luci-app-openvpn) results in version git-2.234... Additionally, the installation or upgrade via the LuCI GUI for the OpenVPN LuCI GUI interface seems to be unreliable. The recommendation is to download manually (opkg download luci-app-openvpn) and install the downloaded file (opkg install WhatEverTheNameOfTheFileIs)
  • Sadly, possibly due to space constraints and the desire to have the smallest binary / executable file possible for OpenVPN, the OpenWRT version does not contain any "help" information (IE, openvpn --help produces no output)
  • Do NOT use periods in the name of an OpenVPN instance in the /etc/config/openvpn file, config openvpn 'WhatEverName' directive. OpenVPN will work, but you won't see it in the LuCI GUI.

To install OpenVPN with OpenSSL and the LUCI GUI for it (under VPN)

  • opkg update
  • opkg install openvpn-openssl openvpn-easy-rsa luci-app-openvpn luci-ssl-openssl (openssl-util and other dependencies will automatically install)
  • OpenVPN will be available under LuCI GUI, VPN, OpenVPN (Remember to refresh the web browser window to display the new category (Firefox: CTRL + Refresh) or log out and log back into the LuCI GUI)

ProFTPD

ProFTPD does not seem to be available as an OpenWRT package anymore. At some point (appx. 2012 or earlier) it was, as evidenced by: https://openwrt.org/docs/guide-user/services/nas/ftp.overview

Use vsFTPD instead.

vsFTPD

Installation

opkg update

opkg install vsftpd

Configuration

Configuration File: /etc/vsftpd.conf

  • Be sure to read the
  • The default configuration file (/etc/vsftpd.conf) for VSFTPD will never work under any circumstances for an OpenWRT router that is in a "normal" / default configuration in regards to its firewall and several other items. It is understood that the OpenWRT developers have better things to do than configuring an old FTP server, but they may as well leave the configuration file blank or perhaps include all of the options, but comment everything out rather than having a configuration file that does nothing more than give an end user false hope.
  • The OpenWRT Package creates an /etc/vsftpd Directory, but it isn't used. Case in point: The default userlist_file name for the OpenWRT version of VSFTPD is /etc/vsftpd.user_list. For other platforms such as CentOS, that file is located in the /etc/vsftpd Directory, but for OpenWRT it is located in the /etc Directory. So why is the /etc/vsftpd Directory created (with nothing in it)? Best guess is that since other Platforms like CentOS that put configuration files in the /etc/vsftpd Directory, there might be some "template" in the vsftpd source code that creates that Directory by default and the OpenWRT developers forgot to disable that function.
  • The /etc/init.d/vsftpd startup script is very simple. So simple in fact that it requires a setting (listen=YES) in the .conf file for vsFTPD for vsFTPD that documentation indicates is set to "yes" if vsFTPD is NOT run via an init.d script. In OpenWRT's case, the startup script is so simple it essentially runs vsFTPD as if it were starting from the command line. This causes no issues, but is a bit counter intutive if one reads the vsFTPD documentation on the "listen" directive.

Below is a working configuration file;

listen_address=W.X.Y.Z
ftp_data_port=20
listen_port=21

# Remember to configure Firewall settings with equivalent values
pasv_enable=YES
pasv_address=W.X.Y.Z
pasv_min_port=10012
pasv_max_port=10021

session_support=NO

# OpenWRT Oddity: Even though the vsFTPD Service / Daemon is started via an init.d script, it is a very simple script that essentially does the same thing as starting vsFTPD from the command line, so the following must be set to YES;
listen=YES

# Banner display does not appear to function in an modern web browser
ftpd_banner=Hello
banner_file=/etc/vsftpd1.banner_file

dirmessage_enable=YES
message_file=.message

max_login_fails=3
anonymous_enable=NO
check_shell=NO

#
chroot_local_user=YES
write_enable=NO
allow_writeable_chroot=YES
local_umask=022

# Equivalent to "Run As" Service / Daemon
background=YES

# Set logged items go to the vsFTPD log instead of the system message log
syslog_enable=NO

log_ftp_protocol=YES
xferlog_std_format=YES
xferlog_enable=YES
dual_log_enable=YES
vsftpd_log_file=/var/log/vsftpd1.standard.log
xferlog_file=/var/log/vsftpd1.xfer.log

local_enable=YES
userlist_enable=NO
userlist_deny=NO

# In OpenWRT, the default location is: userlist_file=/etc/vsftpd.user_list (this is very odd given that OpenWRT creates an /etc/vsftpd Directory)
# On other platforms, like CentOS, the default location is /etc/vsftpd/vsftpd.conf
# Do NOT create the list in anything other than VI or NANO (IE, don't use Windows Explorer, Directory Opus, etc. to create a new file) as there is an issue with Carriage Return / Line Feeds.
# Editing with TextPad later is fine as it seems to respect how the file was created in terms of using CR/LF VS just LF.
userlist_file=/etc/vsftpd1.user_list

In the above working example, of course replace W.X.Y.Z with an appropriate IP Address. Astute readers will notice all the file names that might generally start have "vsftpd" in their names instead have "vsftpd1". The reason for that is because the above working configuration file was used in a situation where a router is configured with two WAN interfaces, with two IP Addresses on two different networks. See the section on Dual WAN vsFTPD for additional information.

The /etc/vsftpd1.user_list contains a list of users that will be allowed to login if the userlist_enable=YES and userlist_deny=NO settings are present.

NOTE 1: If any of the above referenced files (vsftpd1.user_list, etc.) are not present, the vsftpd service will start and appear to be functioning (PS, TOP, HTOP, etc. will all show it as running), but... There will be nothing displayed on client FTP software.

NOTE 2: Users and Groups can be managed by editing the /etc/passwd (User File) and /etc/group (Group File). If Webmin (see below) is installed and properly configured, Users & Groups can be managed through its interface. The useradd command can be added with: opkg install shadow-useradd

NOTE 3: Remember, OpenWRT also uses the /etc/shadow file to store user passwords with MD5 ($1) encryption.

Firewall

Below are the pertienent settings for vsFTPD in the /etc/config/firewall file;

config rule
	option dest_port '20'
	option src 'wan'
	option name 'FTP_TCP_20'
	list dest_ip 'W.X.Y.Z'
	option target 'ACCEPT'
	option family 'ipv4'
	list proto 'tcp'

config rule
	option dest_port '21'
	option src 'wan'
	option name 'FTP_TCP_21'
	list dest_ip 'W.X.Y.Z'
	option target 'ACCEPT'
	option family 'ipv4'
	list proto 'tcp'

config rule
	option src 'wan'
	option name 'FTP_PASV'
	list dest_ip 'W.X.Y.Z'
	option target 'ACCEPT'
	option family 'ipv4'
	list proto 'tcp'
	option dest_port '10012:10021'

And as usual, substitute a functional IP Address for W.X.Y.Z. The above configuration includes settings necessary for Passive FTP (see here for an explanation) used by clients behind a firewall.

Internet Explorer Workaround

If one is using Internet Explorer's FTP capability, there will be an issue if userlist_enable=YES and userlist_deny=NO are set. Solution? Add the users 'anonymous' in the vsftpd.user_list file. Thanks to a top tip from a user named JAYCLEN here: https://bbs.archlinux.org/viewtopic.php?id=158184

vsFTPD for a dual WAN router

According to documentation, the vsFTPD Service / Daemon can only "listen" on a single IP Address (listen_address=W.X.Y.Z). This also appears to apply to Passive FTP settings (pasv_address=W.X.Y.Z). There is a solution. Run multiple instances of vsFTPD. Easy to say, but a bit more complex to accomplish.

Because of the simplicity of the /etc/init.d/vsftpd startup script, it is not possible to use the same binary / executable File (/usr/sbin/vsftpd) for multiple vsFTPD instances. The solution is to create two symbolic links to the /usr/sbin/vsftpd binary / executable File. Be sure to set the permissions on the new startup script to 755: chmod 755 WhatEverScriptFileName (chmod 755 /etc/init.d/vsftpd)

  • ln -s /usr/sbin/vsftpd /usr/sbin/vsftpd1
  • ln -s /usr/sbin/vsftpd /usr/sbin/vsftpd2

This allows one to create two startup scripts in /etc/init.d for vsFTPD (vsftpd1 and vsftpd2) that contain the following (below is the vsftpd1 example);

#!/bin/sh /etc/rc.common
# Copyright (C) 2006-2011 OpenWrt.org

# Remember: There are two symbolic links in /usr/sbin, vsftpd1 and vsftpd2, that point to /usr/sbin/vsftpd

START=50

start() {
	# /var/run/vsftpd is the secure_chroot_dir default value that vsFTPD requires to run
	# It can be shared amongst multiple instances of vsFTPD
	mkdir -m 0755 -p /var/run/vsftpd
	service_start /usr/sbin/vsftpd1 /etc/vsftpd1.conf
}

stop() {
	service_stop /usr/sbin/vsftpd1
}

For the other startup script (vsftpd2), copy and change the above references of vsftpd1 to vsftp2. Be sure to enable (service vsftpd1 enable AND service vsftpd2 enable) both scripts for automatic startup. The reason for needing the above symbolic links can be seen in the above init.d startup script. Specifically the "service_stop /usr/sbin/vsftpd" (minus the 1 or 2 naming convention). If there were two startup scripts using the same /usr/sbin/vsftpd reference, two instances could be started, but when stopping the service / daemon, weird things happen.

Make sure there are two configuration files for each vsFTPD service / daemon as they'll have some unique settings, like IP Addresses, etc.

Also make sure any additional files that are referenced (userlist_file=/etc/vsftpd1.user_list, etc) are duplicated (userlist_file=/etc/vsftpd2.user_list) for each service.

And finally, make sure the /etc/config/firewall file has the additional IP Address included. Simply insert an additional list dest_ip 'A.B.C.D' line after each list dest_ip 'W.X.Y.Z' line in the above firewall example (of course substitute A.B.C.D with an appropriate IP Address).

Webmin

Download the module using WGET: wget http://www.bit-worker.com/download/vsftpd.tar.gz

Install using the Webmin interface: Webmin, Webmin configuration, Webmin Modules, Install from, From local file

Available under: Server, vsftpd

Webmin configuration;

openssl=/usr/bin/openssl
path=/etc/vsftpd1.conf

Also note that vsFTPD module has a behavior where it will add items that are left blank in the GUI interface as commented out configuration items in the /etc/vsftpd.conf file.

For multiple vsFTPD instances, Webmin allows for cloning modules. Remember to change the configuration file location if taking advantage of this feature.

CAUTION!

  • If the configuration of vsFTPD includes the use of userlist_enable or userlist_deny, make sure that the /etc/vsftpd.user_list File is created with VI or NANO as opposed to a Windows utility through Samba. The reason is vsFTPD will not be able to read the file properly if it contains CR/LF (Carriage Return / Line Feeds).
  • If one reads any documentation about the CentOS (possible others) version of vsFTPD, there are references to using the included "user_list" file and a custom named version of the file. After some experimentation, it was determined that it may not work in the fashion noted for the OpenWRT version of vsFTPD as it does for other platforms. Feel free to experiment.
  • It is worth repeating this warning: If any of the files (/var/run/vsftpd, vsftpd1.user_list, etc.) referenced in a vsFTPD configuration file are not present, the vsftpd service will start and appear to be functioning (PS, TOP, HTOP, etc. will all show it as running), but... There will be nothing displayed on client FTP software.
  • If the background= setting is configured as background=NO (as one might do for troubleshooting), it will prevent a router from starting any services after vsFTPD. Since vsFTPD's "start order" is 50, any services after that will not start.
  • Several older forum postings and other web sites, as far back as 2007, make references to installing various additional pieces of software such as kmod-nf-ipvs-ftp along with other kernel modules. They are not necessary.
  • Remember, OpenWRT provides two different vsFTPD packages, one without FTPS capability (opkg install vsftpd) and one with FTPS capability (opkg install vsftpd-tls)

Notes & Questions

It seems very odd that the choice for FTP server that OpenWRT provides is vsFTPD as the latest version is half a decade old. Why not use something that still gets updated on a regular basis like ProFTPD? Perhaps the developers of OpenWRT are attempting to send a quiet message that FTP is not a good thing to use because it is not encrypted. But if that's the case, why not remove every FTP server package that doesn't contain SFTP (SSH FTP) or FTPS (SSL/TSL FTP) functionality?

Tips for Troubleshooting

As with anything related to computers, it can be difficult to figure out what is wrong with a configuration of a service and why it isn't working as expected. vsFTPD is no exception. To eliminate a potential issue, namely the firewall, consider configuring vsFTPD to listen on a LAN interface. This will eliminate problems related to PASV / Passive FTP issues. Also consider using a command line version of FTP as opposed to a browser version. Command line versions of FTP will often times display more error information than a web browser that has FTP capability.

Telnet

TelnetD is supported (and works) on DD-WRT, but OpenWRT has essentially discontinued use of telnet in the name of security. It is possible to build a custom version of the OpenWRT firmware that supports telnetd (and telnet the client), but they've effectively made it very difficult (sad, but probably as it should be). The below section of the source configuration file for OpenWRT says it all;

Code Block
bool "telnetd"
default BUSYBOX_DEFAULT_TELNETD
select BUSYBOX_CONFIG_FEATURE_SYSLOG
help
  A daemon for the TELNET protocol, allowing you to log onto the host
  running the daemon. Please keep in mind that the TELNET protocol
  sends passwords in plain text. If you can't afford the space for an
  SSH daemon and you trust your network, you may say 'y' here. As a
  more secure alternative, you should seriously consider installing the
  very small Dropbear SSH daemon instead:
        http://matt.ucc.asn.au/dropbear/dropbear.html

  Note that for busybox telnetd to work you need several things:
  First of all, your kernel needs:
          CONFIG_UNIX98_PTYS=y

  Next, you need a /dev/pts directory on your root filesystem:

          $ ls -ld /dev/pts
          drwxr-xr-x  2 root root 0 Sep 23 13:21 /dev/pts/

  Next you need the pseudo terminal master multiplexer /dev/ptmx:

          $ ls -la /dev/ptmx
          crw-rw-rw-  1 root tty 5, 2 Sep 23 13:55 /dev/ptmx

  Any /dev/ttyp[0-9]* files you may have can be removed.
  Next, you need to mount the devpts filesystem on /dev/pts using:

          mount -t devpts devpts /dev/pts

  You need to be sure that busybox has LOGIN and
  FEATURE_SUID enabled. And finally, you should make
  certain that Busybox has been installed setuid root:

        chown root.root /bin/busybox
        chmod 4755 /bin/busybox

  with all that done, telnetd _should_ work....

Finding a version of BusyBox that includes TelnetD will not suffice as there are additional items that need to be configured for it to work. However, a telnet client program seems appropriate. See the "signoff" on TELNET here: https://github.com/openwrt/openwrt/commit/a35a7afc9f15b4c084c996ab0dbcd833b45f30d5 But there is an alternative (see the next section)

NETCAT or NC

opkg update

opkg install netcat

Use as a Telnet Client: nc -T -v W.X.Y.Z (-T = Answer using telnet negotiation, -v = Verbose)

Instead of simply pressing the Enter Key in NETCAT, one must instead using the following key commands: CTRL+V, CTRL+M, ENTER (That equates to pressing the ENTER Key. OpenWRT's version of NETCAT in BusyBox does not include the -C switch which allows for easy "carriage returns")

Statistics

CollectD

Task Scheduling with Cron

Additional Information: https://openwrt.org/docs/guide-user/base-system/cron

BackUps

Restic

opkg install restic

To create a backup repository: restic init --repo "WhatEverRepositoryPath"

To make a backup: restic -r "WhatEverRepositoryPath" --verbose backup /WhatEverPathToBackUp

  • Example: restic -r "/mnt/sdb2/RESTIC/WRT3200ACM/" --verbose --tag "What Ever Note" backup /overlay

To view backups: restic -r "WhatEverRepositoryPath" snapshots

  • Example: restic -r "/mnt/sdb2/RESTIC/WRT3200ACM/" snapshots

To restore a backup: restic -r "WhatEverRepositoryPath" restore WhatEverID --target /WhatEverPathToRestoreTo --no-cache (the ID can be obtained from the above "snapshots" command, the target does not have to be the original source, --verbose doesn't work)

There is a really frustrating problem with Restic on OpenWRT when restoring a backup. Many websites recommend setting the TMPDIR environment variable to a location with a lot of space. Sadly that does not work. With careful observation, it was noticed that Retic sets up a cache file in the current user's "home / root" directory. If one is logged on as the "root" user, then this will be the /root, AKA ~ (tilde), Directory. If one has booted up the router using from the internal flash drive while attempting to recover a backup that normally resides on a USB Flash Drive and is normally mounted on /overlay, the 60 or 70 some odd MB on the internal Flash Drive will quickly fill up and cause a no space left on device" error. The simple solution when restoring is to use the --no-cache directive as shown in the above example. For additional information, see here: https://restic.readthedocs.io/en/latest/manual_rest.html (scroll down to the Caching section). Also make sure plenty of RAM is available. IE, the 512 MB built in may not be sufficient, so be sure to enable a SWAP File or SWAP Partition (see section above on SWAP)

Additional Information: https://restic.readthedocs.io/en/stable/ (Note: In some of their examples a tilde ( ~ ) is used, which is a user's home directory)

DD

DD is a program that functions as a cloning utility, among other capabilities and functions (noted in an earlier section for a different purpose). When cloning an entire drive (SSD in the form of an mSATA, M.2 (NVME, NGFF), etc. device) / disk / flash drive* (* the term "drive" used later in this section will apply to whatever storage medium is being cloned), the image file should of couse be cloned to a separate device as with any other cloning software. DD is capable of cloning an entire drive, etc. or a single partition

Note, the DD command is built into BusyBox, but does not have all options available. To take advantage of all the options DD offers, install the full package with this command: opkg install corutils

Below is a generic example command to clone a partition from one drive to another (remember, any data on the destination will be overwritten);

  • dd if=/dev/sdXy of=/dev/sdXy bs=64K conv=noerror,sync status=progress
    • sdXy = X is the drive (as in sda, sdb, sdc, etc.) and y is the partition (sda1, sdb1, sdb3, sdc2, etc.), In Linux, sd = Storage Device, sda is the first storage device which is more or less equivalent to C: in Windows, see https://en.wikipedia.org/wiki/Device_file#Naming_conventions for more information.
    • if = source
    • of = destination
    • conv=noerror,sync = Don't stop for any read errors and make sure any data stored in RAM / Buffers is written to the physical drive
    • status = Show progress
    • bs=block size, amount of source data to be read and then written, IE read 64K at a time, then write that, and repeat.
    • conv = noerror = Don't stop on read errors, sync = If an error occurs use zeros or nuls to pad file, progress=show the progress
Tip for Preparing a Drive or Partition for Cloning to an Image File

Before cloning a partition to an image file, to save space on the image file, "zero out" all unallocated space.

With every file system there are potentially sections of the drive that have had data written to them at some point in time that has since been erased. And as we all know, when a file is "erased" from a drive, the actual file itself is left on the drive and the space it occupied is simply marked as available in a file system. DD has no method of determining alocated or unallocated space. It copies everything. And in the below example where everything it copies is put into a compressed TAR file, compressing a bunch of zeros is very easy to make quite small. IE, "zeroing out" unallocated space on a disk drive really reduces the size of an image file in a compressed file. Advanced cloning utilities like Acronis True Image, Clonezilla, etc. take care of this automatically. But since DD is a multifaceted utility that isn't specifically designed for cloning, it does not have this capability built in.

The below example writes 0s / zeros to a file named ZeroByteFile in a directory named overlay (that happens to be located on a USB Flash Drive) in 64 Kilobyte chunks (of all the words like portion, segment, section, piece, etc., chunk is the most commonly used word in this instance with block coming in second)

  • dd if=/dev/zero bs=64K conv=noerror,sync status=progress of=/overlay/ZeroByteFile (change the destination to suit your needs)
    • When the /overlay partition is full DD will produce an error (IE, the partition is full, which is the objective, so this is a good "error")
  • sync (this writes any unwritten files stored in RAM / Buffer to the physical media)
  • rm /overlay/ZeroByteFile (this deletes the "Zero Byte File" to free up space as the above DD command made the ZeroByteFile as large as all of the available free space on the drive.)
Backing Up using DD Example (AKA Imaging OR IE, Partition Cloning via a TAR / GZ File)

The below example(s) copies a single partition (on a drive that contains multiple partitions) in 64K chunks to an image in a compressed (GZ (GunZip), no need to "TAR" it as there is just a single image file that will be created) file.

  • Generic Example: dd if=/dev/sdXy conv=sync,noerror bs=64K status=progress | gzip -9 -c > /WhatEverPath/WhatEverFile.img.gz (-c=Do not change files, -9=Best Compression, but slower)
    • Example: dd if=/dev/sdb1 conv=sync,noerror bs=64K status=progress | gzip -c > /mnt/sdb2/DD/EXT4a-9.20.2020.img.gz (this file is named after the partition it exists on and the date, but can be named anything)

Remember;

  • The TAR/GZ file will contain a single image file, which in turn contains all of the individual files and directories from the source partition or drive (similar to an ISO File or files created by other cloning software).
  • If DD is used with out GZ, the resulting file produced by DD will be exactly the same size as the partition it is "cloning". This is because DD has no facility to do data compression.
  • Use the above noted (in the section immediately above this one) method to "zero out" unused space as this will aid in reducing the final GZ file size.
  • The GZ method has the distinct advantage of allowing one to open the GZ file and extract out single files (after it is mounted of course, look a couple of sections down).
Tip for Configuring a Cloned Drive after Cloning

WARNING: When cloning an entire drive, everything will be cloned, including the UUID of the partition. One of the "U"s in UUID stands for "unique". After a drive is cloned, the UUID isn't "unique" anymore. Two drives will have the same UUID. If the second flash drive is being used for the sole purpose of backing up settings with the intent of disconnecting the drive and putting it aside, the UUID can be left as it is. If the second drive is left connected the UUID should be changed to to prevent confusion with the source drive. The below command will change the UUID to a random ID (see above section for installing the tune2fs utility)

  • tune2fs -U random /dev/sdXy*
  • It might be necessary to run this command first: e2fsck -f /dev/sdXy (this is equivalent to CHKDSK in windows, where sdXy should be changed to match the appropriate drive, sda1, sdb2, etc.)

This command will change the UUID to the one specified;

  • tune2fs -U UUID /dev/sdXy* (where UUID is the actual UUID)

To verify the change, use the following command;

  • blkid /dev/sdXy

* In the above examples X and y should be replaced with actual mount point references. IE, sda1, sdb3, sde2, etc.

Accessing an Image File (IE, mount it like a drive)

In the above example where a partition was cloned to an image file, utilities like WinRAR, WinImage, etc. cannot be used to access the file. Since the image file represents an entire drive or partition, it can be mounted just like a physical drive.

NOTE: If it is a compressed GZ file, the image must be extracted from the compressed file first: gzip --verbose -d WhatEverFileName (BusyBox has a version of GZIP installed with it, the full gzip utility can be installed with: opkg install gzip) And remember, whereever the file is decompressed, it must have enough space for the original image which will be the size of the partition imaged.

NOTE: The below example is for mounting an Image that was made from a partition, not an entire disk/SSD/USB Flash Drive.

To mount a partition (not a drive);

  • mkdir /tmp/WhatEverMountPoint (the directory can be any directory or file name, an advantage to using the /tmp directory is one doesn't have to worry about dismounting the image as it will not be mounted after a router reboot because the mount point is in the /tmp directory, the image file will exist of course, assuming it is not also in the /tmp directory)
  • mount -o loop -t WhatEverFileSystem /WhatEverPath/WhatEverImage.img /tmp/WhatEverMountPoint
    • -t = the type of file system (this could be -t vfat, -t ntfs, -t ext2, -t ext4 etc., and it should obviously match the type of the original file system, no experiments were done to see if mount utility could "auto detect" the file system, but it may have the capability)
    • -o = Option (let the mount command know it is a "loop" device)

When accessing the mounted image file, the directories shown at the first level may not be familiary as they are organized in the fashion that OpenWRT "sees" them. Open the directory titled upper and you should see all of the directories one is accustomed to seeing at the root level directory.

Good 'ole Fashion, just make a copy

Forget all the fancy backup stuff for this one. Sometimes it's good just to make a manual copy of things. This method works great for configuration files. Not so much to avoid a failed drive, but more to preserve a working copy of a known good configuration file. The idea is whenever one embarks on an upgrade or a major change (even a minor one too) to a service, sometimes it's good to make a copy of a working configuration file. For instance, using the /etc/config/network configuration file: cp /etc/config/network /etc/config/network-09.30.2020 There, a copy of the original file with a date on the end of it. Simple and effective if one needs to take a "single step back", instead of walking through the complexity of restoring files from Restic or a DD Tar.GZ file.

LuCI GUI BackUp

And of course one can also use the LuCI GUI under System, BackUp / Flash Firmware to create a copy of configuration files and even MTDBLOCK contents.

Border Mail System (Postfix, MailScanner, MailWatch, ClamD,

Postfix

Files & Permissions

Configuration: /etc/postfix (that's a directory, not a file)

Startup Script: /etc/init.d/postfix

Main Binary / Executable Files: /usr/sbin/post*

Additional Binary / Executable Files: /usr/sbin/sendmail* (sendmail related compatibility)

Other Binary / Executalbe Files: /usr/bin/mailq, mailq.postfix, newaliaases, newaliases.postfix (sendmail related compatibility)

Library (sub-function) Files: /usr/libexec/postfix

There is no LuCI GUI or any sort of OpenWRT configuration paradigm. Everything can be configured via text files and all safely done with Webmin.

Postfix User and Group items are configured in /etc/passwd and /etc/group automatically.

Owner for /etc/postfix: root:root

Permissions for /etc/postfix: 644

Commands

  • postconf -d (configuration settings)
  • postmap /etc/postfix/transport (updates the transport.db file)
    • Note: Most linux distributions name the transport database file transport.db, but by default the OpenWRT version of Postfix names it transport.cdb
  • postfix reload (after changes are made to master.cf file, or just restart the service)

Warnings

The below warning message(s) are displayed each time Postfix is started. This is because OpenWRT left the default setting smtputf8_enable = 0 when Postfix was compiled. The smtputf8_enable setting relates to other text encoding (UTF8), etc. According to documentation it creates a much larger binary / executable for Postfix. Since OpenWRT focuses on small and compact service files this makes sense. But the fix is easy. Add this line to the /etc/postfix/main.cf file: smtputf8_enable = no

postfix: warning: smtputf8_enable is true, but EAI support is not compiled in
postsuper: warning: smtputf8_enable is true, but EAI support is not compiled in
postfix/postlog: warning: smtputf8_enable is true, but EAI support is not compiled in
postfix/postfix-script: starting the Postfix mail system

MailScanner

Download the latest version from: https://github.com/MailScanner/v5/releases (The year this was written was 2020, so if they've moved onto v6, check the URL)

tar -xvzf WhatEverTheNameOfTheTarGzFile

The installation script ./install.sh relies on the full BASH shell (OpenWRT includes the ASH shell by default): opkg install bash, then type the command bash ./install.sh (plain ASH won't work, they even explicitly state the shebang of their file as #!/bin/bash, not #!/bin/sh, and just for the fun of it attempted to run it with ASH, and it errors out) Read here for more information or to change it permanently: https://www.howtogeek.com/669835/how-to-change-your-default-shell-on-linux-with-chsh/

NTP (Network Time Protocol)

By default OpenWRT provides an NTP Client and Server (suprise, suprise, and a really good thing) within BusyBox. Since most routers (if any) do not provide a method (IE, battery) of maintaining an internal clock when the router is off a method must exist to set the proper time for the router when it starts up. This client service is supplied within the BusyBox version of ntpclient.

It is also possible to install the full version of ntpclient (opkg install ntpclient) along with a LuCI GUI (opkg install luci-app-ntpc). No research was done on the difference between the two versions of the ntp client as the BusyBox version of ntpclient satisfied all functional needs.

For and NTP Daemon / Server, the BusyBox also includes NTPD. A full version of NTPD can be installed (opkg install ntpd), but there is no LuCI GUI inteface as there is with the client. An alternative NTP client, CHRONYD can be installed (opkg install chonry) instead of NTPD. But since the daemon / server version of NTPD in BusyBox will function for client NTP devices (including Windows) no further research was done on alternative NTP daemons / services like NTPD or CHRONYD.

One additional note worth mentioning relates to internet service providers. Some providers, such as AT&T, block client devices attempting to using the NTP protocol to syncronize clocks. Some websites indicate this is a "slow-down" or some other type of limit imposed on the NTP protocol, but the end result is the same. And that end result is the NTP protocol does not work. And that means devices, computers, etc. are not able to syncronize with a time server. AT&T claims this is for security reasons. HA! See more information about it here: https://about.att.com/sites/broadband/network

Webmin

Webmin can be successfully installed on OpenWRT, AND IT IS USEFUL (unlike so many other ignorant (notice the word 'stupid' wasn't used, but they are) web posters claim or question). The end of the previous sentence is in all CAPS and BOLD because of the large number websites and posts that do nothing more than question why anyone would want to install Webmin on OpenWRT instead of just answering the original question of how to install it. Sometimes it is just nice to have a GUI. The editor for config files alone is worth it.

There is however a word of caution to address: Do NOT use Webmin for any OpenWRT services that have an associated LuCI GUI or /etc/config/WhatEverConfigurationFile because modifications made by Webmin will be wiped out by changes made via LuCI or the /etc/config/Files... There are many, many services such as BIND / NAMED, Apache / HTTPD, ProFTPD, OpenSSL for OpenVPN Certificate generation that have no LuCI GUI, nor are they "controlled" or configured via the /etc/config/ Files. That means these services are safe to configure via text or by GUI.

Pre-Installation Tasks for Installing Webmin

Download the Webmin ...tar.gz file: wget https://prdownloads.sourceforge.net/webadmin/webmin-1.953.tar.gz (that's the version number as of this writing, so adjust as they update and locate an updated URL)

Unzip and UnTAR the file;

  • The location chosen when unzipping and untarring Webmin can be the installation directory where the program runs;
    • Typical installation locations for other Linux distributions (do NOT use the /tmp directory or it will be gone when the router reboots);
  • gunzip webmin-1.955.tar.gz and tar xvf webmin-1.955.tar

OR

  • tar zxvf webmin-1.955.tar.gz OR tar zxvf webmin-1.955.tar.gz -C /WhatEverPath/WhatEverDirectory (Example: tar zxvf webmin-1.955.tar.gz -C /usr/local/)

(be patient, there are a LOT of files, even on a fast USB 3.0 flash drive it takes a couple of minutes.

  • If "untarred" a directory other than the installation, do one of the following;
    • Move the untarred directory to the desired location (/usr/local/webmin seems to be a fairly standard location, but of course it can be placed anywhere)
    • When installing use the command (not yet): ./setup.sh /WhatEverPath
  • Before running the setup program;
    • Add the bin Group to /etc/group using this directive: bin:x:1000: (OR, use the groupadd command: groupadd bin, the opkg install shadow-groupadd will be necessary for the groupadd command)
    • Make sure PERL is installed with necessary modules (dependencies will automatically download, and not all of the below are necessary for a base installation of webmin, but come in handy later, and if installing on a USB Flash Drive, as you should be, instead of internal storage, space is not a consideration)
      • opkg update
      • opkg install perl perlbase-http-tiny coreutils-stty perlbase-gdbm-file perlbase-extutils perlbase-storable perlbase-time perl-device-serialport perl-encode-locale perlbase-perlio perlbase-anydbm-file perlbase-anydbm-file perlbase-benchmark perlbase-charnames perlbase-db-file perlbase-dbm-filter perlbase-filecache perlbase-filetest perlbase-getopt perlbase-hash perlbase-sdbm-file perlbase-tap perlbase-test perlbase-unicode
    • Possible Errors & Solutions during and after Installation;
      • "Perl Socket module not installed" Error will occur if perlbase-http-tiny is not installed.
      • "stty: not found" / "Login password: ./setup.sh: line 396: stty: not found" (the line number may be different depending on the version of the setup script an Webmin being installed) Error will occur if coreutils-stty is not installed
      • "The Perl SSLeay library is not installed. SSL not available" Error will occur because the PERL SSLeay module is not available in OpenWRT
      • "Can't locate Time/Local.pm in" / "you may need to install the Time::Local module" will occur if the perlbase-time module is not installed
      • "No dbm on this machine at" error will occur if perlbase-gdbm-file
      • "Error - Perl execution failed  Undefined subroutine &main::get_miniserv_config called at /usr/local/webmin/authentic-theme/session_login.cgi line 17" and / or ""GET / HTTP/1.1" 500 166" (in miniserv.log file) error occurs if perlbase-storable is not installed
      • "Can't locate ExtUtils/CBuilder.pm in @INC (you may need to install the ExtUtils::CBuilder module" error occurs if perlbase-extutils is not installed
      • " can't open '/var/log/webmin/miniserv.pid': No such file or directory" error occurs when stopping Webmin with /etc/webmin/stop
      • failed to open /var/webmin/miniserv.error : No such file or directory at /usr/local/webmin/miniserv.pl line XYZ: This is because webmin wants to put its error log at the /var/webmin location. Nope, how about conforming to some standards and putting in the /var/log directory by default? Up to the end user to configure here: /etc/webmin/miniserv.conf

A Special note on HTTPS (not the Module) for Webmin: Do NOT worry about it. Forget it. Almost impossible to get working.

During installation, Webmin states the Net::SSLeay Perl Module is necessary for HTTPS to work. If not, the Webmin site is only accessible via HTTP.

The instructions on the Webmin site for enabling this functionality are here (Hint: It won't work): http://www.webmin.com/ssl.html

Here's why;

  • The Net::SSLeay Perl Module is not available in OpenWRT, nor is and trying to build said modules results the error "fatal error: EXTERN.h: No such file or directory". OpenWRT does not include some of the GCC files necessary. Several sites (https://www.perlmonks.org/?node_id=1227113) mention using an external cross compile computer as a method of solving the issue
  • Crypt::SSLeay is not available either, becuase there seems to be an issue (https://rt.cpan.org/Public/Bug/Display.html?id=120862) with the Crypt-SSLeay-0.72.tar.gz version that is attempted to download during compile. But even the newer version (https://cpan.metacpan.org/authors/id/N/NA/NANIS/) doesn't work either. Downloading the newer version (https://cpan.metacpan.org/authors/id/N/NA/NANIS/Crypt-SSLeay-0.73_06.tar.gz) and changing the Makefile.PL line ( unless( require( catfile qw(inc IO Interactive Tiny.pm) ) ) { ) to ( unless( require( catfile qw(IO Interactive Tiny.pm) ) ) { ), to get rid of the inc corrects the issue. But then there's a "fatal error: openssl/opensslv.h" issue that is similar to the above mentioned Net:SSLeay issue where OpenWRT does not make certain Devel files available, in this case for OpenSSL, so the cross compiling method is the only solution available.
  • Some information suggests IO::Socket::SSL as an alternative (http://www.cpan.org/authors/id/N/NA/NANIS/Crypt-SSLeay-0.72.readme), but in order to build it, the Net:SSLeay Module is necessary, so that's a circular issue.

Installing Webmin

Run the setup and configuration questions during setup (Note: OpenWRT does not provide the NET::SSLeay Perl Module, so SSL will not be available for Webmin);

  • Detailed instructions to install "The Old Fashion Way..." can be found here: https://doxfer.webmin.com/Webmin/Installation_-_the_old_fashioned_way
  • In chosen Webmin installation directory, run: ./setup.sh /WhatEverPathToInstallWebmin (see above for potential locations)
    • Config Directory: /etc/webmin
    • Log file directory: /var/log/webmin (NOTE: This directory is actually a symbolic link for /tmp, so it will not persist across reboots of a router. If permanent logs for Webmin are desired, change the path)
      • /var/log/webmin (note, this directory is actually located here: /tmp/log/webmin, and needs to be created each time the router is booted as the /tmp directory is just that, temporary)
      • As of the 11.2020 version of Webmin, the default location seems to be /var/webmin, so watch out for that and change it to /var/log/webmin, otherwise, other items described in this article won't work, because Webmin won't start without the correct log path.
    • Full path to perl: /usr/bin/perl
    • MiniServe Configuration (the web process for webmin): /etc/webmin/miniserv.conf
    • Configure OS as: 110 - Generic Linux (it changed to 111 some time in late 2020)
      • OS Choices available when installing Webmin: Pick 110) Geric Linux for OpenWRT (note, the number changes as Webmin adds OSs, so adjust as necessary);
  1) Pardus Linux           2) SmartOS                3) Sun Solaris          
  4) Lycoris Desktop/LX     5) Caldera OpenLinux eS   6) Caldera OpenLinux    
  7) Asianux Server         8) Asianux                9) Whitebox Linux       
 10) Tao Linux             11) CentOS Linux          12) Springdale Linux     
 13) Virtuozzo Linux       14) Scientific Linux      15) Gralinux             
 16) NeoShine Linux        17) Endian Firewall Linu  18) Oracle Enterprise Li 
 19) Oracle Linux          20) Oracle VM             21) XenServer Linux      
 22) CloudLinux            23) MostlyLinux           24) Cloudrouter Linux    
 25) Sangoma Linux         26) Citrix Hypervisor     27) Redhat Enterprise Li 
 28) Redhat Linux Desktop  29) AlphaCore Linux       30) X/OS Linux           
 31) Haansoft Linux        32) cAos Linux            33) Wind River Linux     
 34) Amazon Linux          35) Redhat Linux          36) Fedora Linux         
 37) White Dwarf Linux     38) Slamd64 Linux         39) Slackware Linux      
 40) Xandros Linux         41) APLINUX               42) BigBlock             
 43) Ubuntu Linux          44) Mepis Linux           45) Devuan Linux         
 46) Raspbian Linux        47) Linux Mint            48) Debian Linux         
 49) SuSE OpenExchange Li  50) SuSE SLES Linux       51) SuSE Linux           
 52) United Linux          53) Corel Linux           54) TurboLinux           
 55) Cobalt Linux          56) Mandrake Linux Corpo  57) pclinuxos Linux      
 58) Mageia Linux          59) Mandrake Linux        60) Mandriva Linux       
 61) Mandriva Linux Enter  62) Conectiva Linux       63) ThizLinux Desktop    
 64) ThizServer            65) MSC Linux             66) SCI Linux            
 67) LinuxPPC              68) Trustix SE            69) Trustix              
 70) Tawie Server Linux    71) TinySofa Linux        72) Cendio LBS Linux     
 73) Ute Linux             74) Lanthan Linux         75) Yellow Dog Linux     
 76) Corvus Latinux        77) Immunix Linux         78) Gentoo Linux         
 79) Secure Linux          80) OpenNA Linux          81) SoL Linux            
 82) Coherent Technology   83) Playstation Linux     84) StartCom Linux       
 85) Yoper Linux           86) Caixa Magica          87) openmamba Linux      
 88) FreeBSD               89) DragonFly BSD         90) OpenBSD              
 91) NetBSD                92) BSDI                  93) HP/UX                
 94) SGI Irix              95) DEC/Compaq OSF/1      96) IBM AIX              
 97) SCO UnixWare          98) SCO OpenServer        99) macOS Catalina       
 100) macOS Mojave          101) macOS High Sierra     102) macOS Sierra         
 103) OS X                  104) Mac OS X              105) Darwin               
 106) OpenDarwin            107) Cygwin                108) Sun Java Desktop Sys 
 109) Synology DSM          110) Generic Linux         111) Windows
  • Version: 4

The running Webmin service when viewed by PS or equivalent: {miniserv.pl} /usr/bin/perl /usr/local/webmin/miniserv.pl /etc/webmin/miniserv.conf

Post Installation

The setup script may display some errors, the following is related to having Webmin start automatically and an easy fix);

  • Error: Failed to open /etc/rc.d/init.d/webmin for writing : No such file or directory

There is a choice for solving the above error, choose one of the following two items;

  • In /etc/rc.local (or using LuCI GUI, System, Startup, Local Startup), add the following line: /etc/webmin/start

OR

  • Create the File /etc/init.d/webmin with the following directives;
#!/bin/sh /etc/rc.common

START=99

reload() {
	/etc/webmin/reload
}

restart() {
	/etc/webmin/restart
}

start() {
	mkdir -p -m 0750 /var/log/webmin
	mkdir -p -m 0750 /var/webmin
	/etc/webmin/start
# And don't forget to configure the logfile and errorlog settings in /etc/webmin/miniserv.conf to reflect the above OR leave the Webmin version of the miniserv.conf file as it is and make sure the ...0750 /var/webmin line is above too (then hunt for your log files somewhere besides in a log directory)

# In fact, best to leave that /var/webmin directory creation in place too as webmin puts other temporary crap in there that isn't related to log files.
}

stop() {
	/etc/webmin/stop
}

The above directories are created for logging and the Webmin PID file.

chmod 755 /etc/init.d/webmin (changes the permissions of the above created file), then service webmin enable

The second method has the advantage of making it so these commands work: service webmin stop, service webmin start, as opposed to /etc/webmin/start, /etc/webmin/stop

It also may claim that it has started webmin (immediately after the installation), but sometimes it doesn't really do that, so: /etc/webmin/stop, then /etc/webmin/start

This seems to have been corrected with Webmin versions as of approxomately early 2021: Webmin seems to have an issue detecting ARM CPUs in the Marvell SoC with OpenWRT. This results in an Error 500 Perl execution failed... ...proc::list_processes. To correct the issue modify the /overlay/webmin/proc/module.info File as follows (It disables the Webmin Processor Module because that module does not run correctly on OpenWRT for the AC Series of routers) by removing the generic-linux or *-linux setting;

NOTE: As of 11.2020, a newer version of Webmin overcomes the issue OR version 19.07.04 of OpenWRT's perl corrects the issue (didn't test which one it was, just noticed it)

Original Line: os_support=solaris generic-linux hpux freebsd osf1 irix unixware openserver macos aix netbsd openbsd windows

OR

Original Line: os_support=solaris *-linux hpux freebsd osf1 irix unixware openserver macos aix netbsd openbsd windows

Modified Line: os_support=solaris hpux freebsd osf1 irix unixware openserver macos aix netbsd openbsd windows

Verify the /etc/webmin/config file contains the following settings;

os_type=generic-linux
os_version=4
real_os_type=OpenWRT
real_os_version=19.07.03

Alternative Method of Configuring Webmin settings in /etc/webmin/config file;

os_type=linux
os_version=4
real_os_type=OpenWRT
real_os_version=19.07.03

...however, this necessitates that any Webmin modules that require certain operating systems (apache, bind, etc.) need to have their module.info files modified to include the os_type of linux.

And again, the /overlay/webmin/proc/module.info will need to be modified as above.

Also, most of the Webmin modules will need to be custom configured for the OpenWRT environment in order to function properly. See below...

Adding and Configuring Webmin Features & Modules

Before any modules are moved from the Unused-Modules Category, they must be properly configured for Webmin to detect.

Date and Time

The LuCI GUI does not provide a method to manually change the date or time (see https://openwrt.org/docs/guide-user/services/ntp/client-server). The reason appears to be that the AC Series of routers, among many other router models, lacks the hardware capability to maintain an internal clock when the router is off or unplugged. Instead, it syncronizes with a known NTP (Network Time Protocol) server after booting up. This seems to be confirmed, in that during booting, part of the boot process is to set the clock to midnight January 1, 1970 (see https://openwrt.org/toh/linksys/linksys_wrt3200acm).

Once booted, the the Webmin interface provides a relatively easy method to configure the date and time when the module is properly configured properly. In the default Webmin Dashboard, Time on System;

  • CLOCK, Settings Icon (the gear at the top left of the configuration payne), System configuration, System time setting format, YYYYMMDDHHMM.SS Radio Button

OR

  • /etc/webmin/config: dateformat=dd/mon/yyyy

Remember, the modified time will not persist across reboots. The setting for the format in Webmin will persist, but the AC series of routers, as most others, does not maintain an internal clock when off or unplugged. The time is set by accessing an NTP server when the router boots up.

Users and Groups

System, Users and Groups, Settings;

Password File (User & Password File): /etc/passwd (/etc/passwd- seems to be the OpenWRT template file for passwd)

Group file: /etc/group

Webmin Performance

To decrease the Webmin CPU load on the OpenWRT router (this isn't really necessary for the AC router series as there is "horsepower" to spare);

  • Disable Real-Time Monitoring: Webmin, Webmin Configuration, Themes, Real-time monitoring options, Enable real-time monitoring, NO
  • Reduce Real-Time Monitoring Refresh: Interval for performing update, 10000 (Increasing the default value of 1000 (ms) will also cause delays in information in certain categories, such as Network I/O to be displayed slowly)

Other Notes for Webmin

Some modules, such as NAMED / BIND, may not accurately show the Stop / Start status after a stop or start until after a screen refresh, which is possibly related to the Monitoring Refresh time mentioned above, if increased.

Apache / Apache2 / HTTPD Webmin Module (/etc/webmin/apache/config)

Code Block
allow_virtualmin=0
apply_cmd=/etc/init.d/apache2 restart
test_apachectl=1
pid_file=/var/run/apache2/httpd.pid
httpd_path=/usr/sbin/apache2
test_manual=0
apachectl_path=/usr/sbin/apachectl
auto_mods=1
httpd_dir=/etc/apache2
test_config=1
stop_cmd=/etc/init.d/apache2 stop
max_servers=100
mime_types=/etc/apache2/mime.types
start_cmd=/etc/init.d/apache2 start
graceful_cmd=/etc/init.d/apache2 reload
httpd_version=2.4.43
httpd_conf=/etc/apache2/apache2.conf

BIND / BIND8 / NAMED Webmin Module (/etc/webmin/bind8/config)

The below Code Block contains the settings to customize the Webmin interface for BIND / NAMED;

Code Block
rndc_conf=/etc/bind/rndc.conf
force_random=0
keygen=/usr/sbin/dnssec-keygen
rev_def=0
tmpl_dnssec_dt=1
spf_record=0
by_view=0
other_slaves=1
updserial_def=0
soa_start=0
rndc_cmd=/usr/sbin/rndc
whois_cmd=
allow_wild=1
updserial_man=1
records_order=0
checkzone=/usr/sbin/named-checkzone
updserial_on=1
dnssec_period=21
ndc_cmd=
allow_long=0
tmpl_dnssec=0
allow_underscore=1
rev_must=0
master_ttl=1
confirm_zone=1
restart_cmd=/etc/init.d/named reload
short_names=0
max_zones=999
no_chroot=1
soa_style=0
master_dir=/etc/bind/masters
confirm_rec=1
reversezonefilename_format=ZONE.rev
support_aaaa=1
start_cmd=/etc/init.d/named start
stop_cmd=/etc/init.d/named stop
largezones=0
dnssectools_rollmgr_pidfile=
dnssectools_conf=
signzone=/usr/sbin/dnssec-signzone
no_pid_chroot=0
relative_paths=0
ipv6_mode=1
checkconf=/usr/sbin/named-checkconf
named_conf=/etc/bind/named.conf
dnssectools_rollrec=
slave_dir=/etc/bind/masters
dnssectools_keydir=
rndcconf_cmd=/usr/sbin/rndc-confgen
show_list=1
pid_file=/tmp/run/named/named.pid
named_path=/usr/sbin/named
forwardzonefilename_format=ZONE.hosts
allow_comments=0
extra_forward=
file_owner=bind:bind
default_view=
this_ip=
keys_dir=
extra_reverse=
slave_file_perms=
named_group=
default_master=
named_user=
extra_slaves=
auto_chroot=
chroot=
free_nets=
default_prins=
file_perms=
zones_file=

Sadly, for the BIND / NAMED module, it didn't seem that OpenWRT included the named-compilezone command. However, after some quick research with a major hint (from here: http://www.linuxfromscratch.org/blfs/view/svn/server/bind.html) which included a notation that the named-compilezone command was a symbolic link, then a quick check on a CentOS system which showed the /usr/sbin/named-compilezone pointing to /usr/sbin/named-checkzone, which confirmed the utility as a standalone file does NOT exist, but is simply a softlink to another file. The solution is to add this line to the rc.local file: ln /usr/sbin/named-checkzone /usr/sbin/named-compilezone That way the command is available to Webmin.

Another feature that doesn't work "out of the box" is the View Records File Button. This error message is displayed when clicking on the button: This zone is in raw binary format, and so cannot be displayed as text. But this is not the fault of Webmin, well, not exactly. If they rewrote the code for the module to detect whether the zone file was stored in binary or text format, this issue wouldn't be an issue. The claim by BIND is that storing information in a binary format is better for performance. However, this only applies to very busy DNS servers. For "average" DNS servers, storing the zone records in plain text format will not be an issue. Thanks to a hint from this site: http://geekdom.wesmo.com/2014/06/05/bind9-dns-slave-file-format/, it indicated the setting below applied to both master and slave zone files. To enable the button functionality add the following line to the named.conf file;

  • masterfile-format text;

The above setting can be applied on a zone by zone basis or it can be placed in the main options section to apply to all zones. And again, even though the name of the setting seems to apply to master zone files, it also changes the format setting for slave zone files (IE, there is no slavefile-format directive / command).

Also Note: The Setup RDNC Button in Webmin seems to work (IE, it generates the rndc.conf file, updates the named.conf file, etc.), but the format it applies in the named.conf doesn't seem to work. Syntax wise it is correct, but it doesn't work. Solution? Run the rndc-config command manually;

  • rndc-config > /etc/bind/rndc.conf
  • ...then open the rndc.conf file and copy the section at the bottom into the named.conf file.

PPTP VPN Server Webmin Module (AKA PPTPD / POPTOP)

This module can be used for everything except the PPP Accounts (It can be used, but any changes will not persist across router reboots). The reason is that the /etc/ppp/chap-secrets file (actually a symbolic link to /tmp/etc/chap-secrets) that it accesses is dynamically configured by the /etc/init.d/pptpd startup script based on information in the /etc/config/pptpd file. The Webmin module can be used to view the information, but as noted, do NOT use it to modify user names and passwords for PPTPD. Instead change user names and passwords in the /etc/config/pptpd file.

As noted above in the PPTPD section, OpenWRT does not support the require-mppe-128 option in the /etc/ppp/options.pptpd file. Webmin will insert that value if the "Use 128-bit MPPE encryption?" is set to "Must be used" and that will "break" PPTPD. Leave it set to Default (Allowed). It should also be noted that the mppe-128 is built into the OpenWRT /usr/sbin/pptpd binary / executable file, thus making the setting unneccessary as it is enabled by default (pptp-server.log if enabled shows this: MPPE 128-bit stateless compression enabled).

Below are settings for the PPTPD Module (etc/webmin/pptp-server/config);

pid_file=/var/run/pptpd.pid
pptpd=/usr/sbin/pptpd
log_file=/var/log/ppp.pptpd
file=/etc/pptpd.conf
pap_file=/etc/ppp/chap-secrets
ppp_options=/etc/ppp/options
start_cmd=/etc/init.d/pptpd start
stop_cmd=/etc/init.d/pptpd stop
pptp_ppp_options=/etc/ppp/options.pptpd

The Active Connections feature also appears to be broken for the same reason Webmin can't show processor information with the PROC module. It results in an error of: HTTP/1.0 500 Perl execution failed Server: MiniServ/1.955 Content-type: text/html; Charset=utf-8 Connection: close. Error - Perl execution failed, Undefined subroutine &proc::list_processes called at ./pptp-server-lib.pl

DHCPD Webmin Module (/etc/webmin/dhcpd/config)

As noted in the main DHCPC section, there is no LuCI GUI, nor is there any good reason to stay within the OpenWRT managment paradigm (at least for DHCPD). Unlike some other instances like Samba Server where it makes sense to maintain the "OpenWRT management style" of services, with DHCPD every aspect of Webmin can be utilized. Below are the configuration settings for the DHCPD Webmin Module;

lease_file=/tmp/dhcpd.leases
group_name=0
dhcpd_conf=/etc/dhcpd.conf
pid_file=/var/run/dhcpd.pid
dhcpd_path=/usr/sbin/dhcpd
desc_name=0
lease_tz=0
show_mac=0
dhcpd_nocols=5
show_ip=0
lease_sort=0
display_max=100
dhcpd_version=4.4.1
dhcpd_size=2249541
dhcpd_mtime=1598660246
lease_refresh=
start_cmd=/etc/init.d/dhcpd start
stop_cmd=/etc/init.d/dhcpd stop
restart_cmd=/etc/init.d/dhcpd reload
version=
add_file=
interfaces_type=
hostnet_list=

Items such as dhcpd_version can be modified to reflect whatever version of DHCPD is available in the future. No modifications need to be made to the /overlay/webmin/dhcpd/module.info (assuming the root path of Webmin is /overlay) file as this Module seems to be compatible with every version of DHCPD on every Linux distribution.

The Edit Network Interfaces Button and Interfaces File Type setting in Webmin will not work with OpenWRT.

Samba Server Webmin Module (/etc/webmin/samba/config)

First, if it hasn't already been stated, a LuCI GUI (Services, Network Shares) for Samba exists. AND it makes sense to stay within the OpenWRT management / configuration paradigm for services (/etc/config/samba3 or samba4). Having noted that, the LuCI GUI does not have all the bells and whistles of Webmin, but what is there looks a whole lot better. So for this one, a hybrid approach is best.

Making so Webmin recognizes the Samba Module as an active module requires editing the /usr/local/webmin/samba/module file (assuming /usr/local is the root of the Wemin installation path chosen). For some reason the wildcard version of Linux (*-linux) setting is not respected with OpenWRT / Webmin. That makes it necessary to add the full name of the os_type setting in the /etc/webmin/config file (which should be generic_linux) into the /usr/local/webmin/samba/module.info file os_support setting. See below;

  • Original line: os_support=solaris *-linux aix hpux freebsd osf1 irix openserver unixware openbsd macos netbsd
  • New line: os_support=solaris generic-linux *-linux aix hpux freebsd osf1 irix openserver unixware openbsd macos netbsd

The below configuration for the Samba Webmin Module allows for management of Samba features not included in the LuCI GUI. The Webmin GUI for Samba also provides a path to overstep what should be configured with Samba via Webmin, so use the "restraint" items noted below the configuration section;

smb_conf=/etc/samba/smb.conf.template
samba_server=/usr/sbin/smbd
smb_passwd=/etc/samba/smbpasswd
net=
samba_password_program=/usr/bin/smbpasswd
dont_convert=-499
pdbedit=
text_lists=0
run_from_inetd=0
name_server=/usr/sbin/nmbd
sort_mode=0
swat_path=
samba_status_program=/usr/bin/smbstatus
list_printers_command=lpc status | grep "[A-z0-9]:" | sed -e 's/://g'
smbgroupedit=
start_cmd_wb=fuckytheducky
stop_cmd=/etc/init.d/samba4 stop
stop_cmd_wb=
start_cmd=/etc/init.d/samba4 start
winbind_server=
restart_cmd=/etc/init.d/samba4 restart

Notice a key item in the above configuration settings: smb_conf=/etc/samba/smb.conf.template (NOT smb.conf). This is the key in allowing the Samba Webmin Module to control many Webmin settings. The down side of this is that none of the shared resources will be displayed. But that's OK, because the LuCI GUI interface does display shared resources. Plus any changes made with the Samba Webmin Module would not be persistent and would be overwritten each time the Samba service or router is restarted.

The general rule of what NOT to configure within Webmin is as follows;

  • If it can be configured within the LuCI GUI interface, do NOT configure it with Webmin.
  • If there is an item / setting within the /etc/samba/smb.conf.template of visible within Webmin that is deliniated with a leading and trailing pipe symbol ( | ), do NOT configure it with Webmin.
  • If the Webmin Module is configured correctly with the /etc/samba/smb.conf.template file as the configuration file, not the /etc/samba/smb.conf file, then configuration of shared resources (directories, printers, etc) will not be an issue as they will not be available within the Webmin interface for configuration.

Additional information can be found here: https://openwrt.org/docs/guide-user/services/nas/samba It also illustrates the limits of the what the LuCI GUI interface can and can't do. And it demonstrates at which point editing of the smb.conf.template via a text editor (available within the LuCI GUI on the Edit Template Tab) or in this case Webmin is necessary.

Postfix Server Webmin Module (/etc/webmin/postfix/config)

There is no OpenWRT LuCI GUI interface for Postfix. Nor is there any sort of OpenWRT service managment paradigm implimented in /etc/config for Postfix as there is for many other services. That means it is 100% OK to administer with Webmin with no limitations or fear of interfering with anything else. PERIOD

Below are the configuration settings for the Webmin Postfix Module;

delete_confirm=1
fwd_mode=0
max_records=999
postfix_master=/etc/postfix/master.cf
perpage=999
prefix_cmts=0
max_maps=999
postfix_config_command=/usr/sbin/postconf
postfix_aliases_table_command=/usr/sbin/postalias
mailq_sort=0
postfix_super_command=/usr/sbin/postsuper
postfix_lookup_table_command=/usr/sbin/postmap
postfix_queue_command=/usr/sbin/postqueue
columns=2
mailq_count=0
wrap_width=80
mailq_cmd=/usr/sbin/postqueue -p
mailq_dir=/var/spool/postfix
ldap_doms=0
postfix_control_command=/usr/sbin/postfix
postfix_config_file=/etc/postfix/main.cf
check_config=1
top_buttons=1
index_check=1
delete_warn=1
show_cmts=0
sort_mode=0
postfix_newaliases_command=/usr/bin/newaliases
postcat_cmd=/usr/sbin/postcat
mysql_host=
ldap_attrs=
ldap_id=
ldap_user=
mysql_pass=
reload_cmd=/etc/init.d/postfix reload
mysql_user=
init_name=
ldap_pass=
stop_cmd=/etc/init.d/postfix stop
ldap_host=
start_cmd=/etc/init.d/postfix start
ldap_class=

Third Party Modules (OpenVPN Certificate Authority, not OpenVPN itself as that is configured via LuCI or /etc/config, etc)

Install via the Webmin GUI and remember to configure the module.info file if necessary and settings too. IE, download the module from the Webmin website, and then under the Webmin, Wemin Configuration, Webmin Modules menu, select From uploaded file, and Install Module

OpenVPN (/etc/webmin/openvpn/config);

Code Block
status_cmd=systemctl status openvpn@%s
openvpn_servers_subdir=servers
start_cmd=/etc/init.d/openvpn start
openvpn_home=/etc/openvpn
br_end_cmd=/usr/share/webmin/openvpn/br_scripts/bridge_end
openvpn_keys_subdir=keys
stop_cmd=/etc/init.d/openvpn stop openvpn@%s
down_root_plugin=/usr/share/webmin/openvpn/ovpn_plugin/openvpn-plugin-down-root.so
openvpn_pid_path=/var/run
openvpn_version=2.4.7
openvpn_path=/usr/sbin/openvpn
zip_cmd=/usr/bin/gzip
br_start_cmd=/usr/share/webmin/openvpn/br_scripts/bridge_start
log_lines=200
openvpn_clients_subdir=clients
openvpn_pid_prefix=openvpn/
openssl_home=/etc/openvpn/openvpn-ssl.cnf
openssl_path=/usr/bin/openssl
openssl_version=1.1.1g

Starting and Stopping Webmin

Start: /etc/webmin/start

Stop: /etc/webmin/stop

Additonally, /etc/webmin/start can be added to the /etc/rc.local file to automatically start Webmin at boot.

A service can even be created in /etc/init.d/webmin with the following code;

#!/bin/sh /etc/rc.common

START=99

reload() {
        /etc/webmin/reload
}

restart() {
        /etc/webmin/restart
}

start() {
        mkdir -p -m 0750 /var/log/apache2
        /etc/webmin/start
}

stop() {
        /etc/webmin/stop
}

Sources

https://forum.openwrt.org/t/script-mount-alternate-nand-firmware-linksys/33588

https://forum.openwrt.org/t/solved-how-to-mount-ubifs-in-openwrt-kirkwood/32443/4

Startup Scripts

/etc/rc.local

LuCI, System, Startup, Local Startup

Some useful startup items;

# In order to make the named-compilezone command work for webmin, add the following line (research indicated it was a symbolic link)
ln /usr/sbin/named-checkzone /usr/sbin/named-compilezone


# Create a TEMP Folder for phpMyAdmin
mkdir /tmp/phpMyAdmin
chmod 777 /tmp/phpMyAdmin


# If it is desirable to have the non-active Flash Memory RootFS2 partition available on a WRT3200ACM, then do the following;
#ubiattach -m 8
#mkdir /mnt/MTD8
#mount -t ubifs /dev/ubi2_1 /mnt/MTD8


# If an external drive is used as the overlay, the mtb9 / syscfg partition is attached and mounted by default as /tmp/syscfg as UBI1, so these commands aren't needed, but achieve the same result.  This appears to be a minor flaw in the OpenWRT boot process.;
#ubiattach -m 9
#mkdir /tmp/MTD9
#mount -t ubifs /dev/ubi1_0 /tmp/MTD9


# Webmin Related
# Added as a SERVICE, so not needed
#mkdir /tmp/log/webmin
#/etc/webmin/start



# OpenWRT puts the Apache directory in an unusual location for those with a CentOS / RedHat background.  Instead of modifying all of the default
# locations, it is easier to set up a softlink to the more familiar CentOS locations.  Remember, VAR redirects to TMP, hence the mkdir /tmp/www instead
# of mkdir /var/www
mkdir /tmp/www
ln -s /usr/share/apache2/htdocs /var/www/html
ln -s /usr/share/apache2/cgi-bin /var/www/cgi-bin
ln -s /usr/share/apache2/error /var/www/error
ln -s /usr/share/apache2/icons /var/www/icons

Console Connectivity

Console connectivity on the AC Series of routers can be made via a 6 pin JST-PH 2.0 electrical connector (2.0 refers to the 'pitch' or space between the pins, not a version number) that provides a port with serial communication capability.

Unlike many models of routers that require a similar connector be soldered to a circuit board, the AC Series of routers has this feature installed during manufacturing. Even though the cost is quite small per unit, it can add up to a significant amount of money with a large production run. This implies Linksys was anticipating the router would be used by a modding community. So thank you to the Linksys engineers and management that made sure that feature was included with the router. On the cynical "bean counter" side of things, including a feature which makes it easier to salvage a "bricked" router, also probably cuts down on the number customers attempting to return "failed" units to Linksys.

Serial Ports and TTL Serial Communication

Even thought this port provides serial communication, it should not be confused with a Serial Port (DE-9, AKA DB-9 or DB9) as found on older personal computer or with a USB to Serial Port adapter. A Serial Port on a computer utilizes the RS-232standard for communication. The port on the AC Series of routers uses a similar single-ended signaling method, but with lower voltages (typically 3.3 V - 5.0 V VS voltages up to 15 V for RS-232) often referred to as a TTL or more accurately as a TTL Serial Port or Port using TTL Serial Communication. Many SOC (System on a Chip) and MCU (MicroController Unit) systems besides Linksys use TTL Serial ports as a method of communication and control.

CAUTION: If one connects an RS-232 Serial Port directly to a "TTL Serial Port", at best gibberish will be displayed by whatever terminal / serial console software is being used (PuTTY, SecureCRT, Windows HyperTerminal, etc.). At worst, the higher voltage may permananently damage electronic components on the router's circuit board, rendering it unusable.

Connection with a PC

There are several methods of connecting a PC (Windows, Linux, etc.) to an AC Series router. The simplest of which is a USB to TTL Adapater (originally created by FTDI). USB Adapters typically have a Fanout Pigtail (a term often used when referring to Fiber Optic cables) which allows individual connections to pins on a circuit board port as there is no standard ordering of pins of a TTL Port between manufacturers. Another method utilizes a Serial to TTL Adapter which will likely include a MAX232 (or descendant) IC.

The COM port settings are as follows;

  • 115200 bits per second
  • Data bits: 8
  • Parity: None
  • Stop bits: 1
  • Flow Control: None

Hardware for Serial Connection

After much research and examination of the internal physical layout of the AC Series of routers, the these items seemed the best fit for easily connecting a computer to the router. It allows one to connect everything with no soldering, using standard USB cables. There are of course many other choices, using different hardware ranging from USB to Serial Adapter (with TTL), 9 pin serial ports, etc.

Link as of late 2020: https://www.ebay.com/itm/Switchcraft-EHUSBBABX-USB-B-to-A-EH-Panel-Mount-Feed-Thru-Connector-Black/153365243032

USB A Connector
USB A Connector
USB B Connector
USB B Connector

OR

USB B to USB A with Cable

Link as of Late 2020:https://www.ebay.com/itm/PL2303TA-USB-to-TTL-RS232-COM-UART-Module-Serial-Cable-Adapter-for-Arduino/233559278066

USB PL2303TA Serial to 2.54mm Pitch Molex "70553 Style" Female Pigtail
JST-PH 2.0mm Pitch 6 Pin Female Connector (notice the striped wires that are soldered.





As of early 2021, there doesn't appear to be anyone that manufactures a 6 pin 2.0mm pitch JST-PH female connector / adapter / converter to a "pigtail" 2.54 breadboard / jumper Molex "70553 style" male connector. And that was just when you thought everything existed in the world. Oh, well.

The best "non-soldering" / "plug it all together" solution is the above noted "USB B to USB A with Cable" Connector + the PL2303TA USB (the USB version of a MAX3232) to 2.54 breadboard / jumper Molex "70553 style" female connector to the JST-PH 2.0mm Pitch 6 Pin Female Connector. The stripped off wires that are soldered with fit nicely into the "70553 style" female connector. Everything else is just plugged together, minus the hole in the side of the router for the USB connector. In the end, once put together, it makes it so a router can be connected to a computer via an ordinary USB cable.

The Real Pin # 1

Many website tutorials, YouTube videos, diagrams, and even images on the OpenWRT website show the TTL Serial Port for the AC series of routers numbered from left to right, starting with "pin 1", as viewed from the top / front of the circuit board. This is NOT correct, although both the names / labels of the pins and what their function is (Ground, TX (Transmit), and RX (Receive)), are correct. It is an industry standard to identify "Pin 1" on a circuit board in several manners. The most common methods includes a triangle printed on the circuit board closest to "Pin 1" and a square solder connection (as viewed from the bottom). Another convention that is typically followed, but is not an absolute rule, is putting "Pin 1" closest to the nearest edge of a circuit board. The AC Series of routers all have a square solder connection on the bottom and a triangle printed on top of the circuit board for "Pin 1" on the right side of the connector, as viewed from the top. Since there is no pinout standard for that type of connector, the manufacturer (Linksys in this case) gets to define where "Pin 1" is located. And per the triangle marking, pin closest to edge, and square solder connection pin number one is located as indicated by the below image. PERIOD. Image is courtesy of: http://wtarreau.blogspot.com/2018/

Additional Information

Pinout for TTL Connector on AC Series of Routers
Pinout for TTL Connector

OpenWRT article for WRT3200ACM that applies to other models too: https://openwrt.org/toh/linksys/linksys_wrt3200acm#serial1

For a detailed explanation of Serial Ports: https://en.wikipedia.org/wiki/Serial_port

JST Connector Specifications: http://www.jst-mfg.com/product/pdf/eng/ePH.pdf And a nice video on the subject: https://www.youtube.com/watch?v=wn3ixZ-sv5w

Various comparisons between RS-232 and TTL: https://learn.sparkfun.com/tutorials/serial-communication/wiring-and-hardware

A general tuturial on configuring connectivity with an AC Series router: http://wtarreau.blogspot.com/2018/ (this person has the pin numbers labeled correctly and everyone else's incorrect opinion labeled as "theoretical", see image)


History

One question that has never been precisely determined is this: Which version of Linux is OpenWRT based on? Yes, it is known that the Linksys WRT54G started it all, but what version of Linux in the all the different distributions and branches is OpenWRT based on? OpenWRT is on the chart at the bottom, but no lines are drawn to it.

Perhaps a better question would be: What did Linksys use way back in the early noughties as the basis of their OS for the WRT54G?

Here are some of the first discussions on the subject;

One aptly named project that preceeds the WRT54G and OpenWRT is this: https://en.wikipedia.org/wiki/Linux_Router_Project

The Linux distribution that would seem to be the most modern descendant and perhaps relative of OpenWRT is Alpine Linux.

Package Installation

Here's an all in one line for installing a bunch of useful package. Keep in mind this should only be done if one is using an external USB Flash Drive as even the internal flash storage of a WRT3200ACM won't be enough;

opkg update

opkg install luci-app-advanced-reboot block-mount e2fsprogs kmod-fs-ext4 kmod-usb-storage kmod-usb2 kmod-usb3 ntfs-3g usbutils gdisk cfdisk tune2fs kmod-fs-exfat dosfstools kmod-fs-vfat f2fs-tools kmod-fs-f2fs lsblk ntfs-3g-utils fdisk sfdisk wipefs samba4-server samba4-utils install luci-app-samba4

Tethering

This is the first article written about the Linksys AC Series of Routers that is independent of the main article, but is also included in the main Linksys AC Series Router Configuration Tips for OpenWRT.

Why? The original article was getting way too big. 40,000 plus words. The limitations of the Visual Editor in terms of opening and saving were becoming a drag. This isn't a criticism of the Visual Editor, just a fact.

Even though this article / section is titled in a somewhat open fashion, as if it applied to any OpenWRT device (which it sort of does), it was only tested and intended to be used on the Linksys AC Series of Routers. If you've stumbled upon this page / article, it is also included on the main Linksys_AC_Series_Router_Configuration_Tips_for_OpenWRT article.

Rough Notes

https://openwrt.org/docs/guide-user/network/wan/smartphone.usb.tethering

https://openwrt.org/docs/guide-user/network/wifi/connect_client_wifi

For USB "Mobile Hotspot" (Lumia / Microsoft Terminology) / "Tethering" (somewhat classic terminology): opkg install kmod-usb-net kmod-usb-net-rndis

Additional Packages: opkg install kmod-nls-base kmod-usb-core kmod-usb-net kmod-usb-net-cdc-ether kmod-usb2

IOS: opkg install kmod-usb-net-ipheth usbmuxd libimobiledevice usbutils (plus additional configuration)

When connecting to a Mobile Hotspot or Tethering via Wireless, a reboot of the router may be necessary for the router to connect to the device, perhaps a KMOD thing.

And of course, thankfully a Google search for specifics on specific / granular settings for MWAN3 don't show up in a search, so here's the link: https://openwrt.org/docs/guide-user/network/wan/multiwan/mwan3?s%5B%5D=mwan3

Using the same Wireless Radio for both connecting to Hot Spot and as an Access Point: "Host unreachable.  This might indicate that you are not connected to the network, or might indicate a problem exists on the network between your ISP and the destination host."

Commands: IW, WIFI

There are issues if using a single radio to connect to a hotspot via (Client / STA / Station) virtual interface AND also having an access point (AP) mode operating for wireless clients. Solution: Travelmate;

https://forum.openwrt.org/t/travelmate-support-thread/5155

https://github.com/openwrt/packages/blob/master/net/travelmate/files/README.md

...attempted different start / stop sequences also of the radios and virtual interfaces, but that didn't work.

Commands: mwan3 interfaces, etc.

Issues: When "resetting" the radio, using Travelmate, wireless clients are disconnected and have to reconnect, not a big issue if they're set to reconnect automatically. Also in some instances, until network is restart, MWAN3 and / or travelmate do not allow the local router to ping out successfully when interfaces go up and down, but client machines can.


Also be aware there are some built in delays to all of this, so it doesn't happen automatically.

An alternative would be to purchase a WRT3200ACM or 32X as it has 3 separate radios that don't require the need for Travelmate. Additionally, for under $20, one could also purchase an additional USB Wireless interface such as: https://www.newegg.com/p/0XM-00HB-00005?Item=9SIACMW5833298 for a WRT1900ACS to give it three radios.

Also noticed that for the router, not clients, the routing table is messed up to the point where even when MWAN3 shows an active connection on one of the WANs, the routing table is such that there is no default gatewa configured.

Whatever route table the router uses, it doesn't use the correct one for itself after losing a tethered connection with MWAN3. A service network restart fixes the issue. ip ro and netstat -rn show all of the correct default routes, but the plain route command only shows the wwan route, even if a different one is being used. The following is a workaround for the /etc/mwan3.user file (Network, Load Balancing, Notification);

if [ "${ACTION}" = "disconnected" ] && [ "${INTERFACE}" = "wwan" ] ; then

  # Do something on an ifup event for the wan interface only

ip route add default via 192.168.1.1

fi

The above script adds the correct default route back in...

Conntrack doesn't need to be installed for any of this stuff to work. Might be a good idea if MWAN noted that in the GUI.

And for those of you wondering about what the fork "Firewall Mask" (AKA mmx_mask in the configuration file for MWAN3), it defines the "mark mask" value in IPTABLES, which in turn allows for changes to be made in the Mangle Table for IPTABLES (https://serverfault.com/questions/425835/what-is-the-match-mark-field-in-iptables), and of course Mangle Tables allow for modifications of IP Packet Headers (https://serverfault.com/questions/467756/what-is-the-mangle-table-in-iptables). There is ZERO documentation about this on the OpenWRT site and Google returns about as many useful links to information about what "Firewall Mask" means. This paragraph is almost worth a dedicated page, except it won't rank as high as this one, so here it will stay. OK, what about the OpenWRT documentation that says this value is used in regards to number of WAN connections. https://openwrt.org/docs/guide-user/network/wan/multiwan/mwan3 Really? So what are the different values to set for 1 WAN (err, that would be stupid for MWAN as it is for 2 plus WANs), so what about 3 WANs, 4 WANs, what the fork are the different values for those?!?!?!?

defaultroute in /etc/config/network has nothing to do with anything other than defining a default route in IPTABLES, and it is enabled by default, essentially it is equivalent to not configuring a default gateway for a WAN interface.

DDNS (Dynamic DNS) Client

This article was written about DDNS (Dynamic DNS (Domain Naming System (not Service))) on OpenWRT, but some of it could apply to DDNS using other platforms. On the server side, BIND / NAMED is used instead of the default OpenWRT DNS Daemon / Service, DNSMASQ. DDNS-SCRIPTS is / are the service(s) used on the client side.

To help readers understand things, the terms "user name" and "password" are used in place of TSIG sometimes. Functionally, both are the same. Anyway, the point is to avoid getting sidetracked on the TSIG subject and putting the focus on DDNS and BIND / NAMED.

Problems

OK, first, there are some problems getting the entire DDNS infrastructure to work. If you're not interested in these items, skip down a few sections (don't worry, they're addressed there in terms of proper configuration).

Encryption

The DDNS Client scripts for updating a DNS Server via NSUPDATE expects the "password" (TSIG) to be encrypted / signed using MD5 (HMAC-MD5). The version of the DNSSEC-KEYGEN tool provided by OpenWRT, which is typically used for generating / encrypting / signing a "password" in this form does not support MD5 (HMAC-MD5). Regardless of the arguments pertaining to MD5 encryption / signing, this issue presents a problem. The workaround is easy if you've got a CentOS, Debian, Ubuntu, etc. version of Linux available, as their version of the DNSSEC-KEYGEN utility does support MD5 (HMAC-MD5). As of 11.2020, there is very little information on this subject. This web page notes the issue, but there is no answer: https://github.com/openwrt/packages/issues/8927 According to this documentation, it is sort of implied that BIND / NAMED only uses MD5 (HMAC-MD5) when using TSIG.

Permissions

Out of the box, the permissions on the /etc/bind Directory will cause issues (assuming that's where master and slave files are stored, CentOS stores them in /var/named for example). Regardless of the location, the permissions must be set such that the BIND / NAMED Daemon / Service can write to the Directory (a specific example for this is 'journal' files).

Documenation

OpenWRT provides documentation for DDNS (the client side of things, not the server side) here, https://openwrt.org/docs/guide-user/services/ddns/client and here, https://openwrt.org/docs/guide-user/base-system/ddns It isn't the best written documentation in the world. But those guys are busy with other stuff, so that's OK. It also appears to be written by a non-English speaker, so be prepared for some bad grammar and sentences. But again, that's fine, as that person speaks at least one more language than I do (that's a compliment to them). There are also a couple of additional items that have been added to the DDNS Scripts that aren't addressed by the standard OpenWRT documentation and are only mentioned in passing here: https://github.com/openwrt/packages/issues/2348

Installation and Configuration

Installation for Client and Server

opkg update

Client: opkg install ddns-scripts ddns-scripts-nsupdate luci-app-ddns wget curl *

Server: opkg install bind-server bind-tools (bind-tools includes: bind-rndc bind-check, plus dependencies are all installed)**

If it isn't obvious, the client and server software will not be installed on the same router as DNS server software such as BIND / NAMED rely on having a static IP Address assigned to the OS they're installed on.

See the BIND / NAMED section in this article for additional information on configuration.

The LuCI GUI for the DDNS client is located here: Services, Dynamic DNS

See the Webmin section of this article for a GUI for BIND / NAMED.

* This OpenWRT article discusses and addresses several subjects related to WGET and CURL.

** It is necessary to disable the DNS functionality of DNSMASQ for BIND / NAMED to function properly. If DHCPD is used, and none of DNSMASQ's functionality is necessary, it is highly recommended to remove DNSMASQ instead of disabling it. Odd issues seem to crop up if it remains installed, even if disabled.

Directories and Configuration File Locations

  • /etc/config/ddns: File for configuring DDNS (this file is the one the LuCI GUI uses, but can be manually edited too)
  • /usr/share/ddns: Location for other DDNS items (do not edit these)
  • /usr/lib/ddns: Location for DDNS Scripts (do not edit these)
  • /tmp/run/ddns (Default storage location for DDNS information, can be changed)
  • /tmp/log/ddns (Default location for log files, can be changed)

DDNS References from OpenWRT

Various Options Defined: https://openwrt.org/docs/guide-user/base-system/ddns (keep in mind for this page, it seems to be a bit out of date, there are errors like the stated directory for services files is /usr/lib/ddns/services/"WhatEverFileName" which is actually /usr/share/ddns/list

Configuration for Client

Below is a working /etc/config/ddns configuration file for DDNS Scripts (with Domain Names removed);

config ddns 'global'
	option ddns_dateformat '%F %R'
	option ddns_loglines '250'
	option upd_privateip '0'
	option use_curl '1'

config service 'WhatEverArbitraryName'
	option service_name 'bind-nsupdate'
	option lookup_host 'WhatEverHostName.WhatEverDomainName.WhatEverSuffix'
	option username 'WhatEverUserName'
	option password 'WhatEverMD5EncryptedPassword'
	option domain 'WhatEverHostName.WhatEverDomainName.WhatEverSuffix'
	option enabled '1'
	option ip_source 'web'
	option ip_url 'https://domains.google.com/checkip'
	option bind_network 'wan'
	option force_ipversion '1'
	option interface 'wan'
	option dns_server 'WhatEverDNSServer.WhatEverDomainName.WhatEverSuffix'

It was found that WGET did not work reliably in situation where the router running the DDNS Client Scripts with a private WAN IP Address was behind another router with a public WAN IP Address. So CURL was used to address the issue. DD-WRT addresses this very issue with a radio button choice titled "Do not use external ip check" (worded poorly as negative questions are always a bit confusing), but OpenWRT offers no similar configuration via its GUI or in the configuration file (/etc/config/ddns).

Additional Configuration Example for a Router with Dual WAN Capability

The below example assumes the WAN interfaces (OpenWRT perspective, not from ifconfig perspective) are "wan" and "wwan"

config ddns 'global'
	option ddns_dateformat '%F %R'
	option ddns_loglines '250'
	option upd_privateip '0'
	option use_curl '1'

config service 'WhatEverArbitraryName'
	option service_name 'bind-nsupdate'
	option lookup_host 'WhatEverHostName.WhatEverDomainName.WhatEverSuffix'
	option username 'WhatEverUserName'
	option password 'WhatEverMD5EncryptedPassword'
	option domain 'WhatEverHostName.WhatEverDomainName.WhatEverSuffix'
	option enabled '1'
	option ip_source 'web'
	option ip_url 'https://domains.google.com/checkip'
	option bind_network 'wan'
	option force_ipversion '1'
	option interface 'wan'
	option dns_server 'WhatEverDNSServer.WhatEverDomainName.WhatEverSuffix'

config service 'WhatEverArbitraryName2'
	option service_name 'bind-nsupdate'
	option lookup_host 'WhatEverHostName2.WhatEverDomainName.WhatEverSuffix'
	option username 'WhatEverUserName'
	option password 'WhatEverMD5EncryptedPassword'
	option domain 'WhatEverHostName2.WhatEverDomain.WhatEverDomainName.WhatEverSuffix'
	option enabled '1'
	option ip_source 'web'
	option ip_url 'https://domains.google.com/checkip'
	option bind_network 'wwan'
	option force_ipversion '1'
	option interface 'wwan'
	option dns_server 'WhatEverDNSServer.WhatEverDomainName.WhatEverSuffix'

SPECIAL NOTES;

  • The OpenWRT DDNS Scripts do NOT like or tolerate dashes or hyphens ( - ) in the service name (IE: config service 'What-Ever-Name' will not work and result in nothing showing up in the LuCI GUI)
  • DDNS Scripts (and maybe BIND / NAMED) do NOT like or tolerate underscores ( _ ) in the lookup_host or domain directives (IE: What_Ever_Host_Name.WhatEverDomain.WhatEverSuffix will cause an error)

Configuration for Server

It is not the intent of this article to provide complete documentation on configuring a BIND / NAMED DNS server. This section assumes one has a functioning BIND / NAMED DNS Daemon / Service running.

Generating a "User Name" / "Password"

As noted, the DDNS Scripts only seem capable of using passwords that have been encrypted with MD5 (HMAC-MD5). Some documentation for BIND seems to indicate this is a choice made by BIND / NAMED. DH and SHA256 encryption methods were attempted, but did NOT work. An error in the DDNS log file indicated it was attempting to use an MD5 encrypted password, regardless of how the "password" / "secret" was encrypted.

And also, as noted previously, the dnssec-keygen program (opkg install bind-dnssec) provided by OpenWRT does not support generating MD5 passwords. If one attempts to do so, an error occurs. Solution, again as noted previously, use a different CentOS, or whatever Linux distribution to generate an MD5 encrypted "password" / "secret"

This command will generate a "password" / "secret" for the "user" named "ddns": dnssec-keygen -a HMAC-MD5 -b 512 -n USER ddns

The DDNS Script on the client will also complain that the "password isn't complex enough", but will still function, if a value of less than 512 is used in the above command.

Other utilities, noted here, such as tsig-keygen and ddns-confgen can also generate the appropriate "user name" / "password". But they are not available in any OpenWRT packages.

Directives for /etc/bind/named.conf

Below are the directives to add to named.conf (in OpenWRT, the path is /etc/bind/named.conf);

key "ddns" {
     algorithm hmac-md5;
     secret "WhatEverMD5EncryptedPassword";
};

zone "WhatEverDomainName.WhatEverSuffix" {
     type master;
     allow-update {
     key ddns;
     };
     file "/etc/bind/masters/WhatEverDomainName.WhatEverSuffix.hosts";
     };

The above directives essentially adds a User Name / Password (in encrypted form) that the BIND / NAMED DNS Daemon / Service use to authenticate clients. "ddns" is the User name and the text within, but not including the double quotes, is the password. The zone directive allow-update is one of several ways to restrict dynamic updates (IE, restricting updates to a set group and preventing anyone in the world from sending updates). The above allow-update directive allows anyone using the user name "ddns" (with the appropriate "password") to update the WhatEverDomain.WhatEverSuffix Domain (Example: Google.com). More information on allow-update and update-policy can be found here: https://docstore.mik.ua/orelly/networking_2ndEd/dns/ch10_02.htm

File Permissions for BIND / NAMED Daemon / Server

As it comes from OpenWRT, the bind-server (opkg install bind-server) does not include, specify, configure, or make provisions for any directories that have additional BIND / NAMED files for things such as master and slave zone storage files. Whatever directory is configured for BIND / NAMED to uses for purposes such as that, it must have the proper permissions to create "journal files" as that's where DDNS Client updates are initially stored. IE, updates are not written directly to WhatEverZoneFile.

  • chown bind:bind /etc/bind (for example, as the location for files can anywhere)
  • chmod 644 WhatEverMasterDirectoryForBIND and WhatEverFilesInThatDirectory

The bind User and Group are configured when the bind-server package is installed. If the BIND / NAMED Daemon / Service doesn't have write permissions, the journal file cannot be created. It results in a very, very obscure error in one of the below mentioned log files.

Secure Encrypted Communication Between Client and Server

...coming soon.

Troubleshooting

For troubleshooting on the client side, under Services, Dynamic DNS, Advanced Settings Tab, enable the Log to file Check Box.

For troubleshooting on the server side, the below directives can be added to /etc/bind/named.conf for a "Kick Ash" * amount of logging for BIND / NAMED;

logging {
    channel default_log {
          file "/tmp/log/named/default.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
    };
    channel general_log {
          file "/tmp/log/named/general.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
    };
    channel database_log {
          file "/tmp/log/named/database.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
    };
    channel security_log {
          file "/tmp/log/named/security.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
    };
    channel config_log {
          file "/tmp/log/named/config.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
    };
    channel resolver_log {
          file "/tmp/log/named/resolver.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
    };
    channel xfer-in_log {
          file "/tmp/log/named/xfer-in.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
    };
    channel xfer-out_log {
          file "/tmp/log/named/xfer-out.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
    };
    channel notify_log {
          file "/tmp/log/named/notify.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
    };
    channel client_log {
          file "/tmp/log/named/client.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
    };
    channel unmatched_log {
          file "/tmp/log/named/unmatched.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
    };
    channel queries_log {
          file "/tmp/log/named/queries.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
    };
    channel network_log {
          file "/tmp/log/named/network.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
    };
    channel update_log {
          file "/tmp/log/named/update.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
    };
    channel dispatch_log {
          file "/tmp/log/named/dispatch.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
    };
    channel dnssec_log {
          file "/tmp/log/named/dnssec.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
    };
    channel lame-servers_log {
          file "/tmp/log/named/lame-servers.log" versions 3 size 20m;
          print-time yes;
          print-category yes;
          print-severity yes;
          severity dynamic;
    };

    category default { default_log; };
    category general { general_log; };
    category database { database_log; };
    category security { security_log; };
    category config { config_log; };
    category resolver { resolver_log; };
    category xfer-in { xfer-in_log; };
    category xfer-out { xfer-out_log; };
    category notify { notify_log; };
    category client { client_log; };
    category unmatched { unmatched_log; };
    category queries { queries_log; };
    category network { network_log; };
    category update { update_log; };
    category dispatch { dispatch_log; };
    category dnssec { dnssec_log; };
    category lame-servers { lame-servers_log; };
};

Additional Subjects

DDNS on a Router Behind Another Router

To get it to work properly, below is an example of a router with two WAN connections to the internet where both interfaces are behind other routers (IE, the router with the DDNS service has local IP Addresses assigned to its WAN interfaces);

config ddns 'global'
        option upd_privateip '1'
        option use_curl '1'

config service 'WhatEverService1'
        option enabled '1'
        option interface 'wan1'
        option service_name 'WhatEverService'
        option lookup_host 'WhatEverHost1'
        option username 'WhatEverUserName'
        option password 'WhatEverPassword'
        option domain 'WhatEverDomain2'
        option ip_source 'web'
        option ip_url 'https://domains.google.com/checkip'
        option bind_network 'wan1'
        option force_ipversion '1'

config service 'WhatEverService2'
        option enabled '1'
        option interface 'wan2'
        option service_name 'WhatEverService'
        option lookup_host 'WhatEverHost2'
        option username 'WhatEverUserName'
        option password 'WhatEverPassword'
        option domain 'WhatEverDomain2'
        option ip_source 'web'
        option ip_url 'https://domains.google.com/checkip'
        option bind_network 'wan2'
        option force_ipversion '1'
  • Use the option use_curl '1' directive when using DDNS with a Dual WAN Router
  • If the router with the DDNS functionality is behind another router (like a hotspot, etc.), then the following directives should be configured for proper functionality;
    • use_curl '1'
    • interface 'WhatEverInterface' (not the "ifconfig" or "ip a" name, but the OpenWRT Name found in the LuCI GUI, Network, Interfaces)*
    • ip_source 'web'
    • ip_url 'WhatEverServiceLikeGoogle'
    • bind_network 'WhatEverInterface' (not the "ifconfig" or "ip a" name, but the OpenWRT Name found in the LuCI GUI, Network, Interfaces)*
    • force_ipversion '1'
    • ...and his requires CURL be installed: opkg install curl

* In the above example, wan1 and wan2 are just place holders. In real world circumstances, wan, wwan, etc. would be used, NOT eth1.2

The OpenWRT documentation states WGET is used by default, but for dual WAN routers, make sure the above noted use_curl directive is set.

Some good hints came from here: https://github.com/openwrt/packages/issues/8277

Private IP Address on WAN Interface

It can happen... It's possible an OpenWRT router could be located behind a service provider equipment that provides some sort of "pass through" functionality to the OpenWRT router. If that's the case, it appears from testing the DDNS client service can detect the proper public IP Address, but will not report it through the "Interface Name" method or the "Network Name" method (described above). No further testing was done to see if there were variations that could correct this minor issue as the "Web Service" method (like Google's) works as expected.

Client on DD-WRT

...as of early 2021, this section is not yet complete (and may never be completed because it would take less time to just switch from DD-WRT to OpenWRT)

Assumptions

Sadly, all of the below is predicated on having Entware installed on a DD-WRT router. That's a bit of an undertaking, but is described here: Entware Installation on DD-WRT

If you don't want to try installing Entware, then a good starting point might be the "Do NOT try these things..." in the next section (a bit ironic, but read the last paragraph of that section).

Do NOT try these things...

It was worth it to put this in here because it useful. Unlike every other well meaning tutorial on this, it actually works (IE, the others don't)

First of all, don't try the following;

Having made those disparaging remarks, the below configuration was based on all of the above (sort of). So even though the above seems a bit derogatory, it isn't. Thanks to the pioneering work of those nice people, the below configuration was created.

IP Address from Host Name

This is a prerequisite for having everything for DDNS on DD-WRT

The easiest way to get an IP Address from a host name on DD-WRT with Entware is;

  • opkg update
  • opkg install resolveip
  • Run this command: resolveip -4 www.google.com (and that will result in 172.217.6.36 or any number of other IP Addresses, depending on your physical location)

Special Thanks

Several authors of several web pages stand out in terms of offering really good tips this article is based on. The are noted below;

Testing Things Using NSUPDATE

  • Create a "Key File" in Bind Format using the Key to test against a BIND / NAMED DDNS server;
key "WhatEverKeyName" {
      algorithm WhatEverAlgorithmType;
      secret "WhatEverSecret";
};
  • Create a "Script File" for NSUPDATE (so the individual commands do not need to be entered);
server IPAddressOrURLofWhatEverDNSServer (Example: 1.2.3.4 My.DNSServer.com)
key WhatEverAlgorithm:KeyName KeySecret (Example hmac-sha256:DDNS weiu1-9{}@#$!adk==)
debug yes
zone WhatEverZoneName.Whatever (Example: google.com)
update add WhatEverHostName.DomainName.DomainSuffix. 86400 CNAME ns1 (Example: www.google.com 86400 CNAME ns1)
show
send
  • Run the Command: nsupdate -v WhatScriptFileName -y
  • Or exclude the above key directive in the 'Script File", then run the Command: nsupdate -k WhatEverKeyFileName -v WhatScriptFileName -y

Funky Errors with NSUPDATE?

 nsupdate --version
Error loading shared library libisc-9.18.7.so: No such file or directory (needed by /usr/bin/nsupdate)
Error loading shared library libdns-9.18.7.so: No such file or directory (needed by /usr/bin/nsupdate)
Error loading shared library libisccfg-9.18.7.so: No such file or directory (needed by /usr/bin/nsupdate)
Error loading shared library libirs-9.18.7.so: No such file or directory (needed by /usr/bin/nsupdate)
Error loading shared library libbind9-9.18.7.so: No such file or directory (needed by /usr/bin/nsupdate)

Try reinstalling the bind-libs package: opkg update bind-libs (or remove it and reinstall it, etc.)

Also make sure nslookup is installed: opkg install bind-nslookup

Oh, and just noticed (because generally BIND / NAMED is installed on all documented OpenWRT Routers, not DNSMASQ, it looks like full blown BIND / NAMED must be installed too with DNSMASQ disabled for the Network and Interface Method(s) to function.

Script Error for NSUPDATE (and possibly other scripts too)

If a DDNS update is being sent to a "non-default" port, IE instead of port 53 (udp or tcp), say port 5353, how is that done?

...well, the OpenWRT LuCI interface doesn't give any sort of hint. But, if one looks inside the /usr/lib/ddns/dynamic_dns_lucihelper.sh Script, there's a line that says this: -d DNS-SERVER       => dns_server=SERVER[:PORT]

OK, great. The dns_server / DNS-SERVER variable(s) equate to the DNS-Server Field in the LuCI GUI, so the format would be: W.X.Y.Z:WhatEverPort (where W.X.Y.Z can be an IP Address or Host Name) Right? Nope. It will give this error when the DDNS service is restarted: CRIT : sanitize on dns_server found characters outside allowed subset - TERMINATE

Hmmm, what could it be. Ah! "Behind the scenes", the OpenWRT DDNS update scripts are using the NSUPDATE command / binary from BIND / NAMED (look closely at what gets installed when the ddns-scripts-nsupdate package is installed and you'll notice that the bind-tools package is also installed, which includes the NSUPDATE command). So how does NSUPDATE format the IPAddress:Port thing? They use a space, instead of a colon ( : ). From NSUPDATE help: server address [port]

OK, great! So instead of W.X.Y.Z:WhatEverPort, it would be W.X.Y.Z WhatEverPort. Nope. Same error: CRIT : sanitize on dns_server found characters outside allowed subset - TERMINATE

Why is that?


So in conclusion, here's are the issues;

  • The LuCI GUI gives no indication of what the Host / IP Address [Port] Syntax should be (maybe because nothing will work)
  • The dynamic_dns_lucihelper.sh script has a clear indication of the syntax. But sadly it doesn't work (anymore?, maybe it did in the past or someone has it in mind for the future?).
  • The Regular Express in the dynamic_dns_functions.sh script file does not facilitate or allow spaces or colons (it shouldn't allow colons, but should allow a space because the NSUPDATE command allows for spaces), so this makes it impossible to add / change the default DNS port number (which is NECESSARY sometimes!, see comment below)
  • The "NSUPDATE Script" that is generated and "temporarily" (it only seems to keep the script there if there is an error, otherwise the IP address is stored there) stored in /tmp/run/ddns/WhateverName.DAT contains the NSUPDATE commands, one line of which is: server W.X.Y.Z [and can have the port number, but isn't put there by OpenWRT's DDNS script, but could be put there, but a space, not a colon is the correct syntax]. This means the "NSUPDATE Script" generated by OpenWRT's DDNS script never has the port number included (but it could).

Solution: Change the "Sanitize Regular Expression" (DNS_CHARSET, about twenty or thirty lines down in /usr/lib/ddns/dynamic_dns_functions.sh) to include a space!

  • Current Line of Code: DNS_CHARSET="[@a-zA-Z0-9._-]"
  • Should modified to be (allowing a single space to occur in-between an IP Address or Host Name and a Port Number, in the range of allowed port numbers 0-65535);
    • Allows multiple spaces anywhere: [@a-zA-Z0-9 ._-]
    • Allows a single space in-between the IP Address OR Host Name and Port Number: [@a-zA-Z0-9]*([ ][0-9._-]*)
    • To add to the one immediately above, if one wanted to strip spaces before and after, something like this (but NSUPDATE doesn't seem to care, and in fairness doesn't seem to care about multiple spaces in-between the IP / Host and Port);
      • [@a-zA-^Z0-9]*([ ][0-9._-]*)[\n]$

And I must say, it's easy to change the original Regular Expression to allow a space. But to also restrict the position of the space and the range of numbers is tough. So thanks to this site: https://regexr.com/ for making that testing possible.

It should also be mentioned that there's a comment in the dynamic_dns_functions.sh file that states: # dns character set. "-" must be the last character, so that's why the ._- is at the end of the Regular Expression. Best guess is that it's equivalent to the ; in C or similar type languages, etc. to mark the end of a line.

...didn't want to get too deep into the regular expression stuff, because even the beginning one doesn't check for a valid IPv4 'dotted' IP Address, etc., so there's a limit to the validation here. Decided to cap it at W.X.Y.Z "a single space only here" and a port number. IE, not going to check for or validate a good IPv4 'dotted' IP Address or a Host.DomainName.DomainSuffix, or DomainName.DomainSuffix, etc., again IE, it will be up to the user to establish / know what a valid IPv4 Address is, the proper Domain Name format, and the limit of Port ranges.

Also thought some of the characters in the Regular Expression might need to be escaped with a backslash for the sake of PHP or something, but didn't need to, for example: [@a-zA-^Z0-9]\*\([ ][0-9._-]\*\)[\n]$

And all of the above might be putting the cart before the horse, so here's the 'cart' (IE, the problem that being able to put in a different port number solves): Some internet providers like Comcast use some type of 'transparent' (in real world terms that would be evil and selfish) DNS proxy service that interferes with OpenWRT DDNS updates. This is a known 'issue' (Google it) was tested extensively to verify (a subject for another article coming soon).

Below is a submission to the OpenWRT maintainer of the code to modify the DDNS code to allow for a custom port number;

Maintainer: Michal Vasilek, AKA paper42 
Environment: OpenWRT 22.03.0 r19685-512e76967f (Linksys WRT3200ACM, Marvell mvebu CortexA9)
Source: feeds/packages/net/ddns-scripts
Section: net
Package Version: 2.8.2-25 (It could be solved in other versions, past and future, but this one has the issue)

Description: Neither the LuCI GUI or editing the /etc/config/ddns File allow for including a custom Port Number for the DNS Server.

Why?: Because there is 'sanitation code' in the dynamic_dns_functions.sh file on line 74 in the form of a Regular Expression Variable definition that prevents this from being done.

The LuCI GUI makes no mention of being able to configure a custom port.  However, the dynamic_dns_lucihelper.sh File includes the following line, which implies adding a custom Port Number is allowable or intended or used to be a feature, etc.;

```
 -d DNS-SERVER       => dns_server=SERVER[:PORT]
```

But as noted above, the 'sanitation code' does not allow for a Port Number to be added after the IP Address or Host Name of the DNS Server.

Good News!  The underlying BIND / NAMED command (NSUPDATE) that the script uses, does allow for a custom port number to be used, so this should be easy to implement.  This is from the NSUPDATE help information: server address [port]     (set primary server for zone).

Possible Solution?

The current code for /etc/lib/ddns/dynamic_dns_functions.sh Line 74 is below;
```
DNS_CHARSET="[@a-zA-Z0-9._-]"
```

Suggested Change would be to modify the Regular Expression to allow for a single space between the IP Address OR Host and a Port Number;
```
DNS_CHARSET=[@a-zA-Z0-9]*([ ][0-9._-]*)
```

Important Note: As noted above the dynamic_dns_lucihelper.sh File specifies: SERVER[:PORT]  That should be changed to SERVER [PORT]  The simplest solution seems to be to use a space since NSUPDATE uses a space instead of a colon.  Even though the convention is to use a colon as a separator between the SERVER and [:PORT], there would have to be additional code written to change the colon to a space for the sake of NSUPDATE.


I'm also assuming since it's a script rather than a compile binary file that the package is the same across all distribution of OpenWRT, so is hopefully a quick fix.  This is implied in the package file with this comment in the control section: Architecture: all

And finally: Why make this change? / Why would it be helpful?: There are several internet providers like Comcast X-Finity that impose a 'transparent' DNS proxy service that prevents NSUPDATE, and thus the OpenWRT DDNS Scripts from passing updates to a DNS server like BIND / NAMED.  Without going into detail, the proxy service strips out the TSIG information NSUPDATE sends so when it arrives at the destination DNS server, the update or change request is rejected.

Example(s) of some tests of this 'transparent' DNS proxy service are below;

Attempted DDNS update via NSUPDATE via TCP port 53 through Comcast internet;

;; TSIG PSEUDOSECTION:
ddns.                   0       ANY     TSIG    hmac-md5.sig-alg.reg.int. 1668702339 300 16 vG1mnvKCwArp+t3IFL5NbQ== 32700 NOERROR 0 

; TSIG error with server: expected a TSIG or SIG(0)

Reply from update query:
;; ->>HEADER<<- opcode: UPDATE, status: REFUSED, id:  32700
;; flags: qr ra; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0
Answer:
;; ->>HEADER<<- opcode: UPDATE, status: REFUSED, id:  32700
;; flags: qr ra; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0

Attempted DDNS update via NSUPDATE via TCP port 5353 through Comcast internet;

;; TSIG PSEUDOSECTION:
ddns.                   0       ANY     TSIG    hmac-md5.sig-alg.reg.int. 1668702432 300 16 U2Zm8vhayWBDSKAB1yJNlg== 50001 NOERROR 0 

Answer:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id:  50001
;; flags: qr; ZONE: 1, PREREQ: 0, UPDATE: 0, ADDITIONAL: 1
;; ZONE SECTION:
;fsddns.us.                     IN      SOA

;; TSIG PSEUDOSECTION:
ddns.                   0       ANY     TSIG    hmac-md5.sig-alg.reg.int. 1668702432 300 16 U2Zm8vhayWBDSKAB1yJNlg== 50001 NOERROR 0 

In conclusion, I believe this small modification of the Regular Expression that 'sanitizes' the DNS Server ( DNS-SERVER / dns_server ) Variable(s) and allowing for a custom DNS Port Number to be included could save a lot people from a lot of wasted time.


MWAN Failover

This was a bit of a challenge...

It is worth noting a key piece of information that OpenWRT includes in their documentation on MWAN (and it is in big, bold lettering, because it is important);

  • CONFIGURE THE METRIC VALUE FOR ALL OF THE WAN INTERFACES FIRST!
    • In theConfiguration File, /etc/config/network: option metric 'WhatEverValue'
    • In the LuCI GUI: Network, Interfaces, Edit Button for WhatEverWAN Interface, Advanced Settings Tab, Use gateway metric, WhatEverValue


Samba Scare on WAN

Using the nmblookup utility to check the WAN IP Address of an OpenWRT router, discovered that it reported Samba ports as "filtered". Filtered means it won't respond, but the very fact it even detected it was a bit disconcerting. Especially given that this particular router had the Samba4 service configured such that it would only respond on a single internal LAN IP Address.

So as an extra safety measure added the following to the /etc/config/firewall file (and as usual, substitute the appropriate WAN IP Address(es) for W.X.Y.Z);

config rule
	option dest_port '135'
	option src 'wan'
	option name 'Samba_ALL_135'
	list dest_ip 'W.X.Y.Z'
	option target 'DROP'
	option family 'ipv4'
	list proto 'tcp'
	list proto 'udp'

config rule
	option dest_port '138'
	option src 'wan'
	option name 'Samba_ALL_138'
	list dest_ip 'W.X.Y.Z'
	option target 'DROP'
	option family 'ipv4'
	list proto 'tcp'
	list proto 'udp'

config rule
	option dest_port '139'
	option src 'wan'
	option name 'Samba_ALL_139'
	list dest_ip 'W.X.Y.Z'
	option target 'DROP'
	option family 'ipv4'
	list proto 'tcp'
	list proto 'udp'

config rule
	option dest_port '445'
	option src 'wan'
	option name 'Samba_ALL_445'
	list dest_ip 'W.X.Y.Z'
	option target 'DROP'
	option family 'ipv4'
	list proto 'tcp'
	list proto 'udp'

SPECIAL NOTE: When inserting the above rules, it was noticed that attempting to use the following directive it BROKE all rules that followed (as if it were a syntax error): list proto 'all' (proto 'all' was attempted to and also caused issues). It's as if list proto 'all' and proto 'all' is a syntax error, with the emphasis on 'all'. Changing it to specific protocols like 'tcp' and 'udp' (as shown in the above example) worked great. Lesson? Do NOT use 'all', instead use specific protocol names.

NMAP Utility (Port Scanner)

A handy dandy utility that can be used to scan for open ports: NMAP

opkg install nmap

Scan for common ports: nmap -F WhatEverIPAddress

PPPoE (Point to Point over Ethernet)

The first most important item to remember when a router relies on internet access via DSL with PPPoE, is that IP Frames are limited to 1492 Bytes (not the standard 1500)

OpenWRT claims that the "MSS (Maximum Segment Size) Clamping" Feature (option mtu_fix '1' in the /etc/config/firewall file) takes care of this (the setting even gets added automatically when configuring a PPPoE WAN Interface), but in reality it is safer to manually configure it: option mtu 'WhatEverValue' (1492 in the case of PPPoE) in the /etc/config/network file.

https://en.wikipedia.org/wiki/Point-to-Point_Protocol_over_Ethernet

https://en.wikipedia.org/wiki/Path_MTU_Discovery

Wireless Client Bridge Mode with OpenWRT

The purpose of this information is to configure an OpenWRT based router to function in a manner similar to a DD-WRT Router with a wireless interface configured in "Client Bridge" mode.

In DD-WRT, this is very simple: Select "Client Bridge" under the wireless settings tab. In OpenWRT it isn't as easy.

Important Note

Per the documentation here, it states (paraphrased): If the wireless adapter is in "Client" mode, it will not function as a bridge to devices plugged into the wired LAN ports. This is because most wireless LAN drivers do not support this functionality (IE, it isn't OpenWRT's fault, but a limitation of the hardware drivers).

Origins of this Article

There are two articles the information here is based on (plus actual experience and experimentation)

* These are not derogatory criticisms of the noted articles, just a blunt summary of how they are presented. Without their information as a foundation, neither this article, nor the tested configuration of an actual router could have been done. So thank you to them for the effort on writing the original articles.

A Simpler and more Direct "How to..."

Without going through the complex and non-intuitive UCI commands and / or complex GUI steps to achieve the same results, the solution here will be presented in the form of configuration files.

Assumptions

It is assumed the reader has a general knowledge of networking (IP Addresses, Wireless, etc.) and OpenWRT

To save confusion and focus on clarity of this specific subject, it is assumed the router being configured has a fresh installation of OpenWRT (19.07.05 or higher) installed and the following items are configured as described;

  • The default wireless configuration has been deleted
  • The WAN interface of the router has been disabled and is configured to not start at boot time.

Prerequisites

opkg update

opkg install relayd luci-proto-relay

Configuration Files

/etc/config/wireless

config wifi-device 'radio0'
	WhatEverDefaultsArePresent

config wifi-iface 'wifinet0'
	option ssid 'WhatEverSSID'
	option device 'radio0'
	option mode 'sta'
	option key 'WhatEverKey'
	option encryption 'psk-mixed' OR 'WhatEverOtherEncryption'
	option network 'wwan'

/etc/config/network

WhatEverExistingWorkingSettings, "plus the following added or modified items";

config interface 'wwan'
	option ipaddr 'WhatEverIPAddress'
	option netmask 'WhatEverSubnetMask'
	option gateway 'WhatEverGateway'
	option broadcast 'WhatEverBroadcastIP'
	list dns 'WhatEverDNSServer'
	option proto 'static'

config interface 'ClientBridge'
	option proto 'relay'
	list network 'lan'
	list network 'wwan'
	option ipaddr 'SameIPAddressAsWWAN'

config interface 'lan'
	WhatEverExistingWorkingSettings
	MakeSureNoDefaultGatewayIsAssignedHere
	option ipaddr 'AnIPAddressOnTheSameSubnetAsWWAN'

/etc/config/firewall

config zone
	option name 'lan'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'ACCEPT'
	option network 'lan wwan ClientBridge'

The above settings for /etc/config/firewall can be viewed or configured in the LuCI GUI via Network, Interfaces, "LAN" Interface, Edit Button, Firewall Settings Tab, Create / Assign firewall-zone DropDown (not Network, Firewall).

* Anything that starts with "WhatEver" in the above example should include appropriate settings. See the next sections for some examples to clarify things.

Examples

For the above configuration files;

  • /etc/config/wireless
    • WhatEverSSID: MyWirelessNetwork (This is the name of the wireless network the Client Bridge Router should connect to, similar to how a laptop computer would)
    • WhatEverKey: MyWirelessNetworkKey
  • /etc/config/network
    • WhatEverIPAddress: 192.168.1.10 (This is the IP Address by which the Client Bridge Router can be accessed for administration and configuration purposes)
    • WhatEverSubnetMask: 255.255.255.0
    • WhatEverGateway: 192.168.1.1 (This is not the IP Address of the Client Bridge Router, but a router connected to the internet.)
    • WhatEverBroadcastIP: 192.168.1.255
    • WhatEverDNSServer: 192.168.1.1 (usually the same as the router connected to the internet)
    • SameIPAddressAsWWAN: 192.168.1.10 (This IP Address is assigned to the "RelayD" service
    • AnIPAddressOnTheSameSubnetAsWWAN: 192.168.1.20 (This is a key setting to make it so the router is available via a wired network connection if something fails on the wireless. And yes, contrary to all of the examples on other sites, it can be in the same subnet as the wireless.)
  • /etc/config/firewall
    • lan: This is the default name of the Local Area Network zone for firewall settings
    • wwan: This is the default name of the wireless network zone for firewall settings
    • ClientBridge: This is an arbitrary name that can be set to almost anything (as long as it is under the 15 or so character limit that OpenWRT imposes)

Other Notes

DHCP can be used instead of assigning static IP Addresses, as in the above example. But it is far easier to assign static IPs.

WDS (Wireless Distribution System) can be used as an alternative for this method. But the down side is both the Access Point and Client Routers have to be configured. Using the method described here, nothing special has to be configured on the router providing Access Point service.

Double Check Settings

Double check all of the above settings as any errors may make the router inaccessible. This would require resetting the router to default settings and starting over. Resetting isn't a big deal if this is a 'virgin' router being set up for the sole purpose of being a Client Bridge.

Final Question

In the end, there are some questions that don't appear to have any answers;

  • Why is there a "Client" mode for a wireless adapter if it doesn't accomplish anything other than connecting a router as a client to an access point? IE, if it doesn't act as a wireless adapter for a wired network device, what's the point of "Client" mode?
  • Wouldn't it be better to have a group of packages (opkg install "Wireless Client Mode Package" relayd luci-proto-relay) included as a single package to enable this functionality?

Monitoring Services with Monit

This subject could apply to installations on other platforms besides OpenWRT.

Monit allow for monitoring (via command line or web GUI (http://WhatEverIPAddressOrHostName:2812 (default port))) of services, plus restarting of services if they're not running or not responding.

Installation

opkg update

opkg install monit

Configuration File(s) & Directories for Monit Service

/etc/monitrc (file)

/etc/monit.d (directory)

If configuring in a fashion similar to operating systems such as CentOS, then;

  • Create this Directory: /etc/monit.d
  • Add this line or un-comment this line from /etc/monitrc: include /etc/monit.d/*
  • Add additional configuration files to the /etc/monit.d Directory

Configuration

The default configuration for Monit from OpenWRT is configured in a very secure, with limited capability to view information (IE, it's only available from the command line, see the below configuration section from /etc/monitrc);

set httpd port 2812 and
    use address localhost  # only accept connection from localhost (drop if you use M/Monit)
    allow localhost        # allow localhost to connect to the server and
    allow admin:monit      # require user 'admin' with password 'monit'

The above configuration does not allow for remote viewing via a web browser. But the below configuration allows for a reasonably secure configuration for viewing via a web browser (not including HTTPS, since it is a Local Area Network)

set httpd port 2812 and
    use address W.X.Y.Z     # IP Address that the Monit Web Services "listens" on
    allow W.X.Y.0/24        # IP Address Range that the Monit Web Service allows connections from
    allow WhatEverUserName:WhatEverPassword

Configuration of Individual Service(s) Monitoring

If configured in the manner described in the Configuration File(s) for Monit Service section, each of the following example can be placed in a separate text file in the /etc/monit.d directory.

Apache Example (The below Apache example is very simple. It can also be configured to connect to a website and check for the existence of a specific file);

check process httpd with pidfile /tmp/run/apache2/httpd.pid
start program "/etc/init.d/apache2 start"
stop program "/etc/init.d/apache2 stop"
restart program "/etc/init.d/apache2 restart"
if 5 restarts within 5 cycles then timeout

BIND / NAMED Example;

<syntaxhighlight lang="text">
check process named with pidfile /tmp/run/named/named.pid
start program "/etc/init.d/named start"
stop program "/etc/init.d/named stop"
restart program "/etc/init.d/named restart"
if failed host 192.168.2.1 port 53 type tcp protocol dns then restart
if failed host 192.168.2.1 port 53 type udp protocol dns then restart
if 5 restarts within 5 cycles then timeout

DHCPC Example; check process dhcpd with pidfile /tmp/run/dhcpd.pid start program "/etc/init.d/dhcpd start" stop program "/etc/init.d/dhcpd stop" restart program "/etc/init.d/dhcpd restart" if failed host 192.168.2.1 port 67 type udp then restart if 5 restarts within 5 cycles then timeout </syntaxhighlight> MySQL Example;

check process mysqld with pidfile /tmp/run/mysqld/mysqld.pid
start program "/etc/init.d/mysqld start"
stop program "/etc/init.d/mysqld stop"
restart program "/etc/init.d/mysqld restart"
if failed unixsocket /tmp/run/mysqld/mysqld.sock then restart
if 5 restarts within 5 cycles then timeout

Notifications & Alerts

The Monit service can also send email notifications and alerts. This can get annoying over time, but it is useful if troubleshooting or monitoring a process. The annoyance can also be "reigned in" to a certain degree.

Some Interesting HDD / SSD Monitoring Tips

From: https://www.smarthomebeginner.com/monit-monitor-hard-drive-smart-health-and-temperature/

And to monitor via UUID instead of "SDx" (which is a bit unreliable): https://wiki.archlinux.org/index.php/S.M.A.R.T.

Additional Tips

For monitoring OpenVPN: https://serverfault.com/questions/647506/make-monit-check-openvpn-client-connection-status

Finally / Lastly

Access Monit here (assuming it is set to it's default port and not using HTTPS): http://WhatEverIpAddressOfRouter:2812

...and of course after configuring a new MONIT file, restart the service: service monit restart

Credits & Thanks

A lot of information from here (not sure if this is the original source, but crediting just the same): https://www.smarthomebeginner.com/monit-monitor-file-server-status-samba-nfs/

User Names and Passwords

opkg update

opkg install shadow-passwd shadow-useradd shadow-groupadd

Resetting a Password for OpenWRT with systems that use /overlay

Simply remove the encrypted password from the /etc/shadow file;

Before: root:$1EncryptedPassword#@#asoi41:18475:0:99999:7:::

After: root::18475:0:99999:7:::

Weak Passwords

Not that one would ever want to configure a "weak password", and out of the box, the OpenWRT GUI doesn't allow that. As it should be. But the frustrating part is having that limitation imposed with no way around it. Maybe there is a good reason to temporarily configure a weak password. Is that possible with the OpenWRT LuCI GUI interface? No, not by default. Is there a way around it? Not via that same GUI as far as Google is concerned. But there is a way...

Install the above passwd command, and at a command prompt type: passwd (then enter whatever password one wants)