Most home network setups rely on a very basic configuration in which all devices are connected to the same Local Area Network (LAN) managed by a single device (the ISP-provided router). The main advantage of this configuration is its ease of deployment. However, the simplicity of this implementation comes at the price of multiple disadvantages:
- Limited flexibility: ISP-provided routers are usually far from the state of the art. Their hardware offers limited performance, and restricted expandability (e.g. the number of Ethernet ports is usually limited to four). Additionally, such devices offer at most two possible Wi-Fi access point, the second one usually being suggested for guest access. Although this allows for slight separation between guest and the local network , such routers rarely allow the control of guest internet access (e.g. blocking certain ports).
- Possible lower performance: Because of the centered nature of the setup, the ISP router has to handle every exchange on the network, both wired and wireless. Additionally, because all connected devices are on the same collision domain, the performance of the network as a whole will drop as more devices are connected. The drop in performance is probably insignificant for the vast majority of people due to the low number of connected devices in a household compared to a professional environment. However, the ever increasing number of connected household devices is poised to change that.
- Decreased security: Because all the devices are connected to the same LAN, every device on the network can communicate with every other device. In the case a malicious actor finds their way to the network, they will be able to reach every other connected device. Additionally, because of the limited flexibility of ISP routers, some very helpful security features are usually not available to the user (e.g. configurable Firewalls). Finally, rarely do ISP routers provide the option for firmware upgrade. That, combined with the rarity of regular firmware updates from the ISP makes for a very vulnerable entry-point to the home network.
For the reasons above, and because I thought it would be a fun topic to learn about, I decided to look into alternatives and improvements to my current home network setup. I had already came across the name OpenWrt before, and decided to start there.
OpenWrt (Open wireless router) is a Linux distribution targeted at consumer-grade router devices. It offers support for a wide range of devices1, and provides continuous updates, bug fixes and security patches even long after devices stop being supported by their vendors2. Additionally, OpenWrt offers professional level configuration flexibility. It allows the use of multiple networking functionalities, which are most of the time hidden away in stock router firmware (e.g. Firewalls, Virtual LANs, VPNs, NAT, DNS, and many more). Because it is Linux based, all configurations are text-based, they can be set either through a web-interface or directly by editing configuration files using an SSH connection. OpenWrt also includes a package manager which can be used to install additional packages for even more functionalities. Currently, there are more than 3000 packages available in its repository2. Finally, OpenWrt dates back to 20043, and throughout the years, a great community has gathered around the project, with a rich documentation, and an active forum being available to all who seek help.
Having settled on the software I was going to use, it was now time to pick the hardware it would be running on. I picked the Fritz!Box 7430 to be a first device to practice on and try myself at. The router is the lower-end model of AVM’s flagship DSL router from the previous generation (as of the writing of this article). As such, this router boasts a smaller feature set, and lower-end hardware: it only supports Fast Ethernet (100Mbps) and 2.4GHz Wi-Fi. Moreover, another big limitation of the router is its lack of a dedicated WAN port: The device is intended to be used as a DSL modem, so it only has a DSL/VDSL port for its up-stream connection, along with 4 Ethernet ports for the LAN. We will see how to circumvent this limitation once OpenWrt is installed on the device. Finally, Additional ports include a single USB 2.0 port and one phone port. Figure 2 showcases the positioning of the available I/O ports on the router.
Despite all of these limitations, I still chose the Fritz!Box 7430 for the following two reasons:
- The device is supported by OpenWrt4. This meant an easy installation process already existed.
- I had the device laying around at home: I had bought it one year ago in order to replace an old DSL router, but ended up having to use a different router all together because of some ISP incompatibility. This meant that this whole endeavor would cost me nothing for now, which is always a great motivation to get started with a new project.
Having now settled on both the hardware and software, the next step would be the installation. The installation process of OpenWrt varies a lot depending on the hardware used. This process usually takes one of the following forms (here ranked according to their complexity from easiest to hardest):
- Factory installation: In some cases. it is possible to install third-party firmware using the same process that the hardware vendor makes available for updates of its own firmware. In this case installing OpenWrt is as simple as logging into the router’s web-interface, going to the update section, and uploading the OpenWrt firmware image using a file selection menu. This first possibility is however not that common, as vendors usually implement some checks on the uploaded firmware image, to make sure it does not originate from a third-party source.
- Installation via network boot: A lot of routers implement a “hidden” feature which allows for booting from a firmware image present on another device on the network. Depending on the hardware, the device from which the image will be retrieved can act as either a file server or client. The network booting is successful as long as the remote device serving or pushing the firmware image has a specific configuration which the router expects (e.g. IP addresses or login credentials). In this case, if the configuration expected by the router is known, it can be used to push a third party image onto it, thus making the device boot using third party firmware. However, as the used firmware is only used for booting, it will only remain in volatile memory, and the device will boot into its stock firmware on the next reboot. For this reason, network booting is only the first half of the installation process, the second being the installation of the third-party firmware into the non-volatile memory using the tools available in the booted image.
- Installation using serial port: This installation method is possible if a serial port is made available on the router’s motherboard. In this case, it is possible to log into a serial console, and from there on, instruct the router to boot from a specific firmware image served on a preset address on the network.
- Installation via JTAG: The Joint Test Action Group, or JTAG, is an industry standard for printed circuit board design verification and testing. The JTAG port, is an IEEE-defined interface, which allows debug access to the integrated-circuit on which it is present, by permitting write/read access to arbitrary on-board memory locations. Because of these functionalities (initially intended for electronic design test automation), if the JTAG port has not been disabled by the vendor before the router left the production line, it can be used in order to flash a third-party firmware image into its memory.
In the case of the Fritz!Box 7430, the method supported by OpenWrt is the installation via network boot. As such, OpenWrt’s installation process will be take two steps:
- Step 1: The router will be booted into an OpenWrt image, using network booting, at this point OpenWrt will be living in volatile memory and will not survive a system reboot.
- Step 2: Using the OpenWrt environment, the OpenWrt firmware will be installed into the device’s non-volatile storage.
A brief installation guide is given in the message of the git commit in which support for the Fritz!Box 7430 was added to the OpenWrt project5. In the following two subsections, I will try to complement that installation guide, with additional information it did not cover.
Step 1: Booting from volatile memory
As of this writing, the bootloader in use by AVM on their routers is Eva, which was a complete rewrite of its predecessor Adam2 originally developed by Texas Instruments (get it? Eva came from Adam). Early on in the boot process, the bootloader starts a TFTP server on the device. This TFTP server is hosted on address
192.168.178.1, and admits the user
adam2 with password
adam2. This server remains active for a short period of time (5 seconds), during which, if an initramfs image is pushed into the server (using the previous credentials), it will be used by the bootloader for booting. If no image is pushed to the server during this initial short period, the TFTP server is shut down, and the bootloader simply loads the firmware installed on ROM. The period during which the TFTP server is active can be recognized by the blinking of the power LED of the device.
With this knowledge at hand, we can now understand how, the first step of the OpenWrt installation consists of the following:
- The router needs to be connected through Ethernet cable to another machine which will act as a TFTP client. This machine will have the OpenWrt boot image ready to be pushed to the router.
- The router is powered-on, and within the first few seconds, the OpenWrt image is pushed to the TFTP server residing on the router. For this purpose, address
192.168.178.1, and credentials
The OpenWrt repository includes an
eva_ramboot.py script, which accomplishes exactly this. However, there are a couple considerations which need to be taken into account before making use of this script:
- A very common issue unfolds as follows: As explained earlier, the bootloader starts the TFTP server very early-on in the boot process, and only keeps it active for a few seconds. If the client machine (used to push the OpenWrt boot image to the router) is connected directly through Ethernet cable to the router, its physical network interface might detect the router power-on too late. This is because the client’s interface would have been disabled until after power is detected on the port connected to the router. This can lead to the situation where the TFTP server has already been shut down by the time the client machine detects the router power-on, and activates its network interface. Windows machines seem to suffer more from this issue. Thankfully, there exists an easy solution to this problem: If a switch is used between the router and the client machine, the physical interface of the client machine will remain active even before the router is powered on, thus ensuring that the router will be detected as soon as it boots6
- A second aspect which needs to be considered before attempting to network-boot OpenWrt relates to the partition to which the firmware will be installed in step 2 of the installation. The on-board non-volatile memory is divided into multiple partitions used for different purposes. Among the partitions used, two are reserved to store two versions of the firmware, either of which can be booted by the bootloader. The bootloader knows which of the two partitions to boot by checking the value of its environment variable
linux_fs_start. This variable can take value
0, in which case partition #1 is to be booted during the next boot, or
1, which would lead to partition #2 being booted instead. The reason behind this scheme, is to allow for safe firmware updates: At any time, the router is booted into one of the two partitions. When a firmware update is to take place, the new firmware is installed into the other partition. This way, if the update fails, the currently installed firmware on the device will not be corrupted. If the update succeeds, then the system toggles the value of
linux_fs_start, so that at next boot, the newly installed firmware will be booted.
As I understand it, In step 2 of the OpenWrt installation process, OpenWrt will be installed to partition #1. As such, we need to make sure that partition #1 will be the one to be booted once OpenWrt is installed to the non-volatile memory. To do this, we need to set the value of the
linux_fs_start variable to
To summarize, the following needs to be done in order to correctly network-boot the router using an OpenWrt image:
- Download the OpenWrt source code from its git repository.
- Retrieve the installation firmware from the link mentioned in the device’s OpenWrt page under Firmware OpenWrt Install URL.
- I had initially set the network interface on my computer to a static IP address, but I don’t think it was needed. In case you face issues connecting to the router, you can set your Ethernet interface to have the static IP address withing the range
- With the router not powered-on, connect your computer to one of its LAN ports. As mentioned earlier, you might need to use an intermediary switch to connect the two devices if your interface takes too long to detect the router’s power-on.
- Open a terminal and have the following command on the ready:
ftp 192.168.178.1. We will use this command to log into the TFTP server which will be shortly active during boot. As I understand it, you don’t need to worry about being in the same subnetwork as the IP address of the TFTP server. The router will recognize the destination address and redirect requests addressed to it to its internal TFTP server. The short installation guide from OpenWrt mentions to use the alternative address
169.254.120.1in case the one mentioned above does not work5.
- Power the router on and start spamming the command from the previous step until a connection to the TFTP server is established. When successful, you will be prompted for a username and password to log into the server, use
- Being now successfully logged-in, it is time to check the value of variable
linux_fs_start. In order to achieve this, we start up the debugger binary, and use it to issue the
ftp> debug bin ftp> quote GETENV linux_fs_start
If this variable has value
1we need to switch its value to
0using the following command:
ftp> quote SETENV linux_fs_start 0
We can now stop the debugger (
Ctrl+d) and log out of the FTP server:
- Now that we know the correct boot partition is set, we can use the OpenWrt source code we downloaded in 1. in order to push the initramfs image to the TFTP server so the bootloader uses it for boot. Navigate to the
openwrt-masterdirectory containing the OpenWrt source code downloaded in 1., and call the
eva_ramboot.pyscript with the following arguments:
$ ./eva_ramboot.py 192.168.178.1 /path/to/initramfs
The first argument given to the script is the IP address of the TFTP server hosted on the router. The second argument is the path to the initramfs file downloaded earlier in 2.
At this point, the router will reboot, and load the initramfs. OpenWrt should be booted, if no static IP was set on the computer earlier, an address in the range
192.168.1.0/24 will be assigned to it. OpenWrt’s web-interface can be reached on address the
192.168.1.1, or using the hostname:
openwrt.lan. You can log into the web-interface using the username
root, by default no password is set.
Step 2: Installing to ROM
Following the steps in the previous section, the system is now booted into OpenWrt. We now need to install the OpenWrt firmware into the non-volatile ROM storage of the router. Achieving this is the easy part of the installation process. All we need to do is use the web-interface’s Firmware update menu, and upload the correct firmware image to be flashed into storage. The image to be used can be found in the device’s OpenWrt page under Firmware OpenWrt Upgrade URL. Before going further, make sure that you have set the
linux_fs_start variable to
0 as explained in Step 1. After selecting the file and launching the upgrade, the router will install the firmware into ROM, when it is done, it will reboot into it.
Using a LAN port for WAN access
As mentioned in Section: Fritz!Box 7430, the router does not have a dedicated WAN port. This is an issue since my plan is to connect the Fritz!Box to my ISP router for Internet access. Thankfully, using to the rich feature set of OpenWrt, we can easily circumvent this limitation by using one of the four available LAN ports as a WAN port. This can be achieved by following the next two steps:
- We need to create a Virtual LAN (VLAN) which will contain the LAN port we want to use for WAN access. This allows to separate this ports from the remaining three, and have the router treat it as if it were on its own separate LAN.
- OpenWrt will treat the VLAN created in the previous step as a separate Ethernet device We can now create a new network interface on this Ethernet device, and configure it to function as a WAN port (i.e. use a static IP address, use the ISP router as a default gateway, and disable DHCP for it).
The following two sections detail these two steps.
Step 1: Setting up the VLAN
If the router in question supports VLAN functionalities (as is the case of my Fritz!Box), VLAN options will be available in the Switch section of the OpenWrt web-interface (menu Network > Switch). Figure 3 illustrates what the default OpenWrt VLAN configuration for my router looks like. The following is a list of what is most notable about this default configuration:
- The configuration shows five ports, even though the device has four physical ports. This is because the
CPU (eth0)port, does not correspond to any physical port, but is a logical representation of the communication interface between the router’s CPU and the onboard switch.
- There already exists a VLAN set by default by OpenWrt. This VLAN has the ID
1, and includes all ports of the router. The VLAN ID is what allows the switch to distinguish traffic from different VLANs. This ID will be tagged by the switch into data packets depending on which port they were received on, and what VLAN that port belongs to. The switch, can then decide which ports to forward the packets to, depending on whether they belong to the same VLAN or not.
- Within each defined VLAN, a port can be in either one of three states:
- Tagged: This means that the switch will tag all packets going out on this port with their VLAN ID. A port should be tagged if it will be connected to a VLAN-aware device (e.g. a managed-switched). The switch will also expect packets coming in from these ports to be tagged with the corresponding VLAN ID. A port can be set as tagged for multiple VLANs.
- Untagged: The switch will remove the VLAN ID tag from packets destined to these ports, before they are sent out. This is probably the state most used for a given port, and is to be used for ports intended to be connected to devices that are not VLAN-aware, (e.g. unmanaged switches, end-devices) As such, incoming packets will not have a VLAN ID tag, and it is up to the switch to tag each packet with the correct ID. Finally, on some routers, a port can be set as untagged for one VLAN at most (this is the case for mine).
- Off: A port set to this state for a certain VLAN will not receive any packets belonging to that VLAN. A port can be set as off for multiple VLANs.
With this knowledge, we can now make better sense of the default configuration in Figure 3: The single default VLAN has all physical ports as untagged because they are expected to be connected to end devices. The CPU port is set as tagged because all packets are passed to it for management and routing, so it needs to be aware of the tags set on the different data packets.
Figure 4 shows the configuration we will be setting, in order to use one of the ports (
LAN1) for WAN access, here are our modifications to the default configuration:
- A new VLAN is created with ID
2, this will be the VLAN we will use for the WAN. I have also added a description for the two VLANs for better readability.
- The port
LAN1is set to be off for
VLAN1and untagged for for
VLAN2. This is because we don’t need whatever device we will be connecting on the
LAN1port (in this case the ISP router) to be aware of its VLAN ID.
CPU (eth0)port is set as tagged for both VLANs. This is because we want all packets from both VLANs to be tagged with their IDs before being forwarded to the CPU, this way the CPU can know which VLAN they have originated from, and decide how to manage them.
- The remaining three ports are still untagged in
VLAN1, this way we can still used them for our LAN needs. They are set to be off on
VLAN2, because we do not need any of them for our WAN access.
That is all the configuration we need. After saving and applying the new settings, a new VLAN will be created, and port
LAN1 will be as good as if it were physically separated from the other ports on the router. All that is left now is to create a new network interface to use this port for WAN access.
Step 2: Creating the WAN interface
We will need to create a new network interface to go along with our newly created VLAN. This can be done in the Network > Interfaces menu. Figure 5 shows the interfaces created by default by OpenWrt for my Fritz!Box router. There are three default interfaces defined:
LAN: As its name indicates, this interface is intended to manage the LAN network. It is defined on device
br-lan. This is the logical device which combines/bridges the wireless and wired LANs of the router. I am not showing it here, but as general settings for this interface, OpenWrt defines a static IP for this interface (
192.168.1.1) and enables a DHCP server with range (
192.168.1.1/24). Finally, this interface is assigned within the
lanfirewall zone (green color).
WAN6: These are interfaces defined for WAN access.
WANis defined on the
WAN6is defined on the same device (through the use of an alias device). This interface allows to add IPv6 DHCP support to the
WANinterface. Additionally, Both interfaces are in the
wanfirewall zone (red color). Finally, Both these interfaces seem to not be active, as they cannot identify their corresponding network device. This might be because of lacking support for DSL support by OpenWrt for my router. As I am not intending to use DSL anyway, I did not look further into this.
Figure 6 shows our target interface configuration:
- I removed the
WAN6interfaces and replaced them with a newly created
WANinterface which has the following settings:
eth0.2. This is the logical device corresponding to the VLAN we created in Step 1. OpenWrt names VLAN devices following the naming scheme
ethX.Y, where X is the physical interface index (in our case
0for the physical interface
eth0), and Y the VLAN ID (
2in our case).
- Protocol: Static IP. Since we will be connecting this interface to the ISP router, we want this port to have a static IP instead of a dynamic one, so we always know what address to use in order to reach it.
- IPv4 address and netmask:
255.255.255.0, respectively. I used these values since my ISP router uses the default subnet
192.168.0.1/24. I have no other device in my network with IP address
192.168.0.2so I chose it as a static address for my router.
- IPv4 gateway:
192.168.0.1. This is the local IP address used by my ISP router.
wan. This setting will have the effect of all requests coming into the Fritz!Box from the WAN port being dropped by its firewall. This means that the FritzBox will not be reachable by devices connected to the ISP router. I chose this setting because it was the quickest to reach a working setup, and it can always be changed later. Additionally, the router not being reachable from outside of its internal LAN was not that big of an issue for me at that point.
- DHCP Server: disabled. My ISP router has its own DHCP server and will handle requests on its LAN.
- I changed the device used by the
eth0.1. I don’t think this is a necessary step. I made the change for two reason: Firstly, as mentioned earlier the
br-lanis a bridge interface combining the wired and wireless ports of the router. However, for some reason, the wireless interface is not working on my router, and its corresponding menu (Network > Wireless) is missing on my web-interface. So the bridge LAN is effectively just my wired LAN. Secondly, I wanted to make sure my understanding was correct: Since OpenWrt sets a default VLAN with ID
1and assigns all ports to it, using device
eth0.1should be fine. Another change I made was, I did not set any default gateway or custom DNS on the
LANinterface. The default gateway did have the value
192.168.0.1 (wan)grayed out, so I am assuming it is using that value by default (maybe because it is the value used on the other interface). I believe DNS would still work without any issue even without specifying a custom server, and will resort to using the default gateway for that. Finally, it is important that the LAN and WAN use different subnets. The default range used by OpenWrt and my ISP’s router being respectively
192.168.0.1/24, I had nothing to change about this configuration.
That should do the trick! After saving and applying the new settings, there is no need to reboot the router for the changes to apply. Connecting the Fritz!Box to the ISP router using the port
LAN1 now allows access to the Internet. Simultaneously, devices connected on the other ports of the FritzBox should behave as if connected to the same LAN.
I am very happy with how things turned out. I managed to get an extra router with a large feature set without having to spend too much on it (in fact I haven’t spent a penny so far). I would like to spend more time learning about the different available features, and how I can use them to optimize my home network configuration. I have already learned a lot just in figuring out how to set the VLAN and network interface I needed for Internet access, and am looking forward to learning more. I found OpenWrt’s configuration backup feature to be extremely helpful, and made great use of it whenever I was unsure about a setting I was about to change. The restore feature was very handy whenever something went wrong and I wasn’t sure which change I had made caused that.
For all its advantages, I have already found OpenWrt to be slightly limited in some aspects. In particular, I was looking forward to very frequent package updates. However, because OpenWrt’s package manager does not handle dependencies at all, it is actually very discouraged to update packages separately, as there is a good chance it would lead to broken environments and unbootable systems7. The correct way to perform updates is to actually upgrade the whole firmware instead of the individual packages. The OpenWrt firmware is still updated very frequently, so I guess it’s not that big of an issue that individual packages should not be updated. Another limitation I faced does not actually stem from OpenWrt but from the hardware it is used on. Most routers will have very limited onboard storage (in my case 38MB). This limits the number of packages that can be installed on the system. The good news is that most OpenWrt packages are extremely light, so I don’t think space will be an issue.
In the future I would like to try something with more horsepower to manage my home-network. I am currently considering using OpenSense on a NUC or mini-PC, but that is still in early planning, and I have a lot to learn before I can attempt that. In the mean-time, my Fritz!Box with its freshly installed OpenWrt will make for a great learning tool, and solution to segregate a couple devices on my home network. There’s a good change I might be covering that next.
OpenWrt - Upgrading OpenWrt firmware using LuCI and CLI#Package upgrade warning ↩