Ad

Sunday, January 17, 2021

Redundant Internet access for your mission critical Home Automation setup

Introduction

When you decide to setup your own infrastructure in order to depend less on cloud providers, whether it be for saving money (depending on what you will be doing) or just for the sake of improving the technical knowledge, having more control, or both, you know you will be flying solo, at least to some extent. 

But regardless of whether you decide to build your own infrastructure or go for the turnkey solution and put most of your home automation in the cloud, there will likely always be something physical in your side to enable connectivity to exist. This can be in the form of a Fiber to the Home (FTTH) link, a Cable (DOCSIS) access, a DSL line, a 4G/LTE modem, a SpaceX Starlink satellite connection, or anything else in the consumer space that I may be missing.

The bottom line however, is that depending on your provider and the hardware that is employed, the single form of access you decide to use will sooner or later, for a shorter or longer period, fail and become unavailable. While your ISP may have a robust infrastructure at its core, from the subscriber perspective there is only a single link that no matter how good it is, it cannot be assumed to never fail.

Hardware Setup

Requirements

That is where my article comes into play: while today it may not be a challenge for most users, especially those who make basic use of their internet access, to when facing an outage, to just turn on their smartphone personal hotspot and go from there. Is is not quite the case when you have "things" in the house, and these need to be connected for you to be able to remotely control.

With that in mind, and having this scenario as a personal context as well, I have setup and will show how I have achieved a relatively low cost procedure for enabling a redundant and permanent Internet access setup for the home.

The first thing that I had to consider was how to pull this off without diving into solutions that cross the enterprise level, cost-wise.

The main element here is the router. This is the workhorse that defines the bridge between your home and its devices, and the connectivity to the outside. My goal here was to select a device that would both be inexpensive, but have slightly above average specifications, enough to allow me to setup the redundant Internet and related software support, but also have room for future needs (e.g. VPN).

For a while I have been a fan of opensource solutions in this space, and OpenWRT in particular is a project that I use for quite a while. Even though it is not all roses when it comes to its features and support for various devices, overall it is one step above in flexibility when compared to most firmwares in consumer devices such as routers, access points and other embedded devices.

I aimed at obtaining a router that would have at least the following specs:

  • 256 MB of RAM
  • 64 MB of flash memory and/or a MicroSD card slot;
  • a powerful enough SoC/CPU, e.g. something multi-core with several hundred MHz of clock speed, and with some hardware acceleration of the network functions, e.g. NAT;
  • be properly supported by OpenWRT;
  • be easy to flash, without having to resort to exploits or difficult hardware tricks. Ideally something with a unlocked u-boot bootloader or similar (capable of loading sysupgrade images);
  • Featuring WiFi 802.11ac;
  • Featuring 1 Gbps Ethernet at  least on the WAN port;

From a search to the market, one device that I have found as "ideal" for this kind of enhanced consumer use,  was the Turris Omnia:

https://openwrt.org/_media/media/turris/turris_omnia.jpg?cache=

This router was the result of a crowdfunding campaign, and besides being able to run open source software such as OpenWRT, its hardware designs are open and published to the community.

It is a great piece of hardware from what I could read about: it features a 1.6 GHz dual-core Marvell Armada CPU and has 2 GB of RAM and 8 GB of flash memory. As it has 3 Mini PCI Express slots, the user can select the most appropriate selection of Wifi and/or LTE/4G hardware for connectivity. It also has 5 LAN ports and 1 WAN port, all 1 Gbps.

The catch however was the cost (around 300 USD depending on vendor and configuration), which didn't capture much enthusiasm from my side at least considering the budget that I had in mind for this solution. Not to say that it is not worth the price, because it probably is, but it begins to cross that enterprise level I mentioned before. For a more serious application it is probably the way to go, and still stay opensource.

Selected Hardware

Going through the usual Chinese online retailers, I found one device that seemed interesting, and the cost was not too much outside my expectations: the Unielec U7621-06 (https://openwrt.org/toh/unielec/u7621-06):

 



It is based on the popular MediaTek MT7621 SoC, and the model I have chosen (there are different variants and customizations possible) featured 256 MB of RAM, and 16 MB of flash. Like the Turris Omnia, it has 3 Mini PCIe ports as well. It can be purchased with a combination of different WiFi cards. In my case, I have selected a card featuring the MT7612E (802.11bgnac) and another one featuring the MT7603E (802.11bgn):

 

All the Ethernet ports are 1 Gbps (4xLAN, 1xWAN) and in spite of the small amount of flash (16 MB), I was not too concerned, because it features a MicroSD slot.

I ended up purchasing this unit, knowing that OpenWRT has good support for the MT7621 chip in particular, and the WiFi cards were already covered by the newer and more properly written mt76x drivers. Besides the device being shipped with a a preinstalled version of OpenWRT, the project site has precompiled images for this device as well. At the time I shelled out about 80 Euros for the unit, via Aliexpress. Given the price, I incurred in customs duties which is an aspect to take into account.

Hardware for the secondary Internet access

So given my main goal of implementing a redundant connectivity, I still had to look for the hardware that would provide the secondary Internet connection. At first, and given that the device had a USB 3.0 port, I considered purchasing a regular LTE dongle. This didn't seem like a very "professional" approach though, and would occupy the USB port, which could be useful for a different purpose in the future. Given that an extra Mini PCIe slot was available and a SIM card slot was present, I gave focus to looking for an LTE adaptor that could go inside the router.

I found a lot of options in the market, and many were quite expensive. However (again in Aliexpress) I found numerous boards that were at cheaper price levels, and given the brand and presentation, I suspected that these could be refurbished boards, eventually recovered from thrown away laptop computers.

One aspect about 4G/LTE radios is that given the highly variable spectrum licensing circumstances in the different countries, these are manufactured in several variants, each tailored for a specific set of LTE bands. Not always is there an overlap between the bands supported by the device, and the bands that the carriers in a given country operate in.

So I had a bit of a dillema. Either I would purchase one of these cheaper LTE cards, most of which tailored for the bands used in Mainland China, or I would buy a more expensive one that would cover more of the bands available in Portugal.

As such, I targeted a specific board which I found it was relatively common, and seemed to be supported by OpenWRT: the Huawei ME906s-821:


From its specs, this board was capable of operating in the B1,B3,B8 FDD bands, and B39,B40,B41(38) TDD bands. It was therefore tailored for the Chinese territory. Regading Portugal, I learned that LTE bands in use were B3, B7 and B20, so the only overlapping band was B3. This was not awesome, but I also found that in my location and carrier, only the B3 band was being used, so it was not much of an issue. 

Also even if the B3 band becomes unavailable, given that these cards (just as cell phones) feature UMTS and GSM, on lack of coverage, are always capable of falling back to one of these legacy technologies, thus providing continued connectivity. That was my reasoning for committing to this compromise solution. Given that this would be a secondary Internet connection in case of temporary failure, I also wasn't too concerned about eventual bandwidth tradeoffs.

And so I went. The router arrived first and I used it for a while until the LTE card also arrived.

Assembly

For this card to operate, I would need to have two additional antennas mounted on the case. This required drilling two new holes in the aluminum case of this router, in order to expose the RP-SMA connectors to where the antennas would attach to:

The Huawei LTE card was simply attached and screwed into the available Mini PCIe slot:


The antennas

As I wanted to be able to test the setup, and the LTE antennas I have ordered had its arrival delayed, I looked for an alternate, eventually temporary solution: I had several RP-SMA antennas from old WiFi gear. These of course, were tuned for the 2.4 GHz band, and not for the 1800 MHz of the LTE B3 band. As such to use these optimally, I would need to do a small modification to its size.

These basic WiFi antennas are generally no more than a dipole, which is basically a straight length of copper wire, generally about 1/4 wavelength of the frequency in question. In the case of the 2.4 GHz, this corresponds to about 31 mm. For the 1.8 GHz of LTE this would be about 42 mm. There is normally another similar length of wire in the opposite direction of the antenna element, which forms the ground element.

As such, in order to modify the antenna for 1.8 GHz, I simply extended the main dipole element with extra 11 mm of copper wire, in order to achieve the 42 mm of 1/4 wavelength of this frequency:



 
While it is possible that the antenna is not optimally tuned and I do not have the tools for that effect (e.g. a VSWR meter for microwave RF), it is likely that the radio implementation of the card provides some built in tuning which should be able to some extent to compensate for a poorly matched antenna (these cards have to operate in a variety of frequencies, and is nearly impossible that the antenna will be well matched for all). But this is just a supposition, hence I preferred to use a modified antenna than to just stick a WiFi antenna into it.

Software Setup

I expected that after adding the LTE card, quite a number of things had  to be installed and configured in the router in order for it to work.

The first confusing detail that I stumbled upon, was the fact that the card didn't seem to have been detected, as I could not see anything obviously new when listing the PCI devices:

 

root@griffinnet-main-router:/etc/config# lspci
00:00.0 PCI bridge: Device 0e8d:0801 (rev 01)
00:01.0 PCI bridge: Device 0e8d:0801 (rev 01)
00:02.0 PCI bridge: Device 0e8d:0801 (rev 01)
01:00.0 SATA controller: ASMedia Technology Inc. ASM1062 Serial ATA Controller (rev 01)
02:00.0 Network controller: MEDIATEK Corp. Device 7612
03:00.0 Network controller: MEDIATEK Corp. Device 7603

I imagined that a new device with the "Huawei" string should appear here. I also read people reporting that the unused mPCIe slots in this router would normally be disabled by default, requiring a GPIO to be set in order to power the cards.

Reading a bit further about the device, I learned that the only thing that it exposes on the PCI bus is a USB host adapter. The modem itself is a USB device that is internally attached to this USB bus.

As such I decided to install "usbutils" in order to get more information about eventually connected USB devices.

Upon running the "lsusb" command, voilá, the modem appeared as one of the detected devices:

root@griffinnet-main-router:/etc/config# lsusb
Bus 001 Device 002: ID 12d1:15c1 Huawei Technologies Co., Ltd. ME906s LTE M.2 Module
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

With that out of the way, and confident that the card was working, I moved on with setting it up.

Setting up the Huawei ME906s-821 LTE modem

I will further detail the steps as a guide, as it may prove useful for other users with a similar setup:

1. Part of procedure was based on this page:

https://openwrt.org/docs/guide-user/network/wan/wwan/ltedongle


1.1. Install the needed packages:

# opkg update
# opkg install usb-modeswitch kmod-mii kmod-usb-net kmod-usb-wdm kmod-usb-net-qmi-wwan uqmi kmod-usb-net-cdc-mbim umbim modemmanager usbutils



(you will need a router with sufficient storage space for all this software)


2. in order to get the /dev/cdc-wdm0 device to appear, modify the /etc/usb-mode.json file to correctly setup
your card.

2.1. Find the vendor_id:device_id of your card by running the command:

# lsusb
Bus 001 Device 002: ID 12d1:15c1 Huawei Technologies Co., Ltd. ME906s LTE M.2 Module
...



2.2. Search the id in the file, and replace the entry corresponding to your device, by the following:


"12d1:15c1": {                                                   
        "*": {                                                   
                "mode": "Huawei",                                
                "msg": [  ],                                     
                "config": 3                                      
        }                                                        
},     



3. Save the file, and reboot the router:


# reboot

Setting up the new network interface


4. Use modemmanager instead of uqmi, in order to control your card and setup the wwan interface. From my experience, the later proved not to work with my setup:

4.1. Edit the /etc/config/network file, and a configuration similar to:


config interface 'wwan'
    option proto 'modemmanager'
    option device '/sys/devices/platform/1e1c0000.xhci/usb1/1-2'
    option apn 'NOS'
    option username ''
    option password ''
    option pincode  ''
    option lowpower '1'



Replace the values of device, apn, username, password and pincode with the values that
are correct for your device, SIM card and carrier.

In order to determine the device string, run the command:


# mmcli -m 0
...
  -----------------------------
  System   | device: /sys/devices/platform/1e1c0000.xhci/usb1/1-2
           | drivers: cdc_mbim
           | plugin: Huawei
           | primary port: cdc-wdm0
           | ports: cdc-wdm0 (mbim), wwan0 (net)
  -----------------------------
...


5. Finally reboot your router.

6. If all worked correctly, you should now have the wwan0 interface up and running:


# ifconfig -a wwan0
wwan0     Link encap:Ethernet  HWaddr ****
          inet addr:****  Bcast:****  Mask:255.255.255.252
          inet6 addr: **** Scope:Link
          UP BROADCAST RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:182451 errors:0 dropped:0 overruns:0 frame:0
          TX packets:127468 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:173836183 (165.7 MiB)  TX bytes:47867814 (45.6 MiB)


You may also run the mmcli command again, to confirm the cellular network connection status:


# mmcli -m 0
...
  Status   | unlock retries: unknown (3)
           | state: connected
           | power state: on
           | access tech: lte
           | signal quality: 74% (recent)
  -----------------------------
  Modes    | supported: allowed: 2g, 3g, 4g; preferred: none
           | current: allowed: 2g, 3g, 4g; preferred: none
  -----------------------------
  IP       | supported: ipv4, ipv6, ipv4v6



Configuring the Internet connection failover/balancer using MWan3

In order to properly take advantage of having multiple WAN interfaces present in the router, it is necessary to add some capabilities to the router. Basically we want to be able to monitor the status and connectivity of each of our interfaces, and when the main interface is down or cannot reach hosts on the Internet, we want to be able to route traffic to the secondary interface, in this case our LTE cellular access.

For that effect, I have chosen the preferred solution in OpenWRT, namely MWan3.

This tool can basically be used to load balance between multiple Internet connections, or to failover between these, depending on how we configure the its settings.

Prior to installing mwan3, the first thing you should configure are the metrics of your interfaces. Because now you have two interfaces that provide you connection to the internet, there will be two corresponding default gateways in OpenWRT's routing table. In order to make sure that your primary Internet access is chosen by default, even if for some reason mwan3 is not working, we need to play with the interface metrics. Here in interface with a lower metric value will have higher priority that the interface with a greater value. As such we want to add for example the metric 0 to our wan interface, and 10 for the cellular modem interface, so that we only use the later if for some reason the traffic cannot be routed to the first. Open the /etc/config/network file, and add the metric field to the wan and wwan interfaces:

config interface 'wan'

        option ifname 'eth0.2'

        option proto 'static'

        option ipaddr '192.168.2.100'

        option gateway '192.168.2.1'

        option netmask '255.255.255.0'

        option metric '0'


config interface 'wwan'

        option proto 'modemmanager'

        option device '/sys/devices/platform/1e1c0000.xhci/usb1/1-2'

        option apn 'NOS'

        option username ''

        option password ''

        option pincode  ''

        option lowpower '1'

        option metric '10'


Now we need to install the mwan3 package and its luci extension to be able to manage and configure via the web UI:

# opkg update

# opkg install mwan3 luci-app-mwan3

Next, and considering that the wwan interface was previously setup and tested successfully, it needs to be configured for MWan3.

Once the packages are installed, restart the router. A new menu entry should be visible, under Network > Load Balancing:

 

In this Globals tab you may want to keep the default update interval of 5 seconds, or tune to a lower value (I have adjusted to 3 seconds in order to help with the response times).

Next, in the Interfaces tab, you may want to delete all the entries, except the wan entry. Create a new entry called wwan:

Edit the wan interface settings. I personally have chosen to reduce some values to improve the response time. Namely:

Tracking reliability: 2

Ping count: 1

Ping timeout: 2 seconds

Ping interval: 3 seconds

Failure interval: 3 seconds

Recovery interval: 3 seconds

Interface down: 2

Interface up: 2

Copy all the settings present in the wan interface, into the newly created wwan interface.

In the members section, I have kept the following two members (this assumes that you only have two Internet connections to failover between):

 

The metric defines the priority. A lower value means higher priority. In this case the interface with metric 1 (wan) will take precedence (as long as it is online) over the wwan interface, which has metric 2. Given that we are giving different metric values for each interface, the Weight parameter becomes irrelevant. In the case I kept the default value of 3 in both.

If instead of failover you want to load balance between the interfaces, in this case you will want to assign the same metric to both, and play with the weight. I.e. if you want to distribute the traffic equally between both interfaces, you will want equal weight in both.

In the policies you can define which interfaces are member of a given policy. With this, you can defines rules so that certain types of traffic can be segregated to be routed to a specific interfaces or through the interfaces added as members of a certain policy. If you just want to failover between two interfaces any kind of traffic, you can define just one entry called "balanced" for example:

 

In the rules tab, you may keep the default rules, and make sure these are assigned to the "balanced" policy:

Integration with Home Assistant

The last tab I found it to be quite useful, and my example serves to illustrate what can be done with this.

Basically here you are able to edit the /etc/mwan3.user file, which is a script that is executed, everytime MWan3 detects anything with the interfaces or decides to failover traffic.

In order to take advantage of this, I have installed the Mosquitto client (a client to the Mosquitto MQTT broker), so that on Home Assistant I can take actions based on these MWan3 events.

For installing the MQTT client, run the following command, or install the mosquitto-client-nossl from the web UI:

# opkg update

# opkg install mosquitto-client-nossl

Next, in the Notifications tab of MWan3 (or editing directly the /etc/mwan3.user file), add the command for publishing messages when network state change or failover events occur:

/usr/bin/mosquitto_pub -h 192.168.1.20 -p 1883 -u sonoff-device -P sonoff-device -t "/network/events" -m '{ "'${INTERFACE}'_state" : "'${ACTION}'" }'

Next in Home Assistant, define a couple of new sensors. These are going to be where we track MWan3 state changes and be able to perform automations based on it.Edit the configuration.yaml file in your Hass.io instance:

  - platform: mqtt

    name: router_wan_state

    state_topic: "/network/events"

    value_template: '{{ value_json.wan_state }}'

  - platform: mqtt

    name: router_wwan_state

    state_topic: "/network/events"

    value_template: '{{ value_json.wwan_state }}'

And finally we define the automations that will use this "sensor". Create a new file for the automation, or add your scripts to the automation: section of the configuration file. In the following example, for each type of event we perform a different action (sending different notifications to the user):

- id: wan_down

  alias: wan_down

  trigger:

    platform: mqtt

    topic: /network/events

  condition:

    condition: template

    value_template: "{{ is_state('sensor.router_wan_state', 'disconnected') }}"

  action:

    - service: script.notify_users

      data:

        message: "Acesso Internet por cabo indisponível. A utilizar rede celular."


- id: wan_up

  alias: wan_up

  trigger:

    platform: mqtt

    topic: /network/events

  condition:

    condition: template

    value_template: "{{ is_state('sensor.router_wan_state', 'connected') }}"

  action:

    - service: script.notify_users

      data:

        message: "Acesso Internet por cabo retomado."


- id: wwan_down

  alias: wwan_down

  trigger:

    platform: mqtt

    topic: /network/events

  condition:

    condition: template

    value_template: "{{ is_state('sensor.router_wwan_state', 'disconnected') }}"

  action:

    - service: script.notify_users

      data:

        message: "Acesso Internet por rede celular indisponível. Sem redundância de acesso."


- id: wwan_up

  alias: wwan_up

  trigger:

    platform: mqtt

    topic: /network/events

  condition:

    condition: template

    value_template: "{{ is_state('sensor.router_wwan_state', 'connected') }}"

  action:

    - service: script.notify_users

      data:

        message: "Acesso Internet por rede celular disponível. Redundância retomada."


Instead of calling the service called script.notify_users, you can add whatever action(s) you want, in response to these events.

No comments: