WeOS
5.20.1

# Firewalling with NetBox

## Introduction

ⓘ Note

This feature is only available in certain products and to selected customers.

This document shows how to use the NetBox application container to create an advanced router and firewall using nftables.

    WeOS                                  # Firewall Application
         .-------.  .-------.             # .-------.  .-------.
         | vlan1 |  | vlan2 |             # | vlan1 |  | vlan2 |
         '---+---'  '---+---'             # '---+---'  '---+---'
             '-.      .-'                 #     '---.  .---'
           .---+------+---.               #       .-+--+-.
           |      br0     +-------.       #       | eth0 |
           '-+---+--+-----'       |       #       '--+---'
       .-----' .-'  '-.           |       #          |
    .--+-.  .--+-.  .-+--.    .---+---.   #          |             .----.
    |eth1|  |eth2|  |eth3|    |  fw0  |   #          |             |eth4|
    '----'  '----'  '----'    '---+---'   #          |             '----'
                                  '------------------'

Our application will take exclusive control of the `eth4` port, which is connected to our ISP, i.e. it is our WAN interface. We will then connect one end of a veth pair (`fw0`) to the host system bridge (`br0`) and the other end (`eth0`) will be places in the application’s network namespace.

We’ll then setup the application to configure the necessary network interfaces and load our firewall configuration, when the application starts.

To complete this howto you will need:

- A device running WeOS 5.y.0 or later, with support for Application Hosting.
- A NetBox application image which is compatible with your device. See the NetBox release archive for the latest version.

## Persistent Storage

Before we can configure our application instance, we need to import the application image. And before we can do that, we must make sure that we have a compatible source of persistent storage for the image.

In order to protect the host system from unintended wear of the internal FLASH, caused by a malfunctioning application, application images and data use external storage. Because of the nature of the data being stored, the underlying filesystem must support commonplace UNIX filesystem features like symbolic links. Notably, this disqualifies the most commonly used filesystem for USB sticks and SD-cards, VFAT. It is recommended to format your storage to use a journaling version of the Extended filesystem, i.e. ext3 or ext4. For testing purposes, WeOS can format the external storage to use ext2 which, while not journaling, can be used to store application data.

    example:/#> media
    example:/media/#> show
    MEDIA        NAME         TYPE         SIZE         USED         USE%
    External     usb          vfat         1.9G         20.0K        0%
    example:/media/#> format external ext2

    Warning: Formatting this media removes all files stored on it!
             This process cannot be reversed, do a backup first.

    Do you still want to proceed (y/N)?y

    Formatting: 100% \ [================================================]

    Format successful!
    example:/media/#> show
    MEDIA        NAME         TYPE         SIZE         USED         USE%
    External     usb          ext2         1.8G         32.0K        0%

## Importing NetBox

Now that we have a source of persistent storage, we can import the image:

    example:/#> app image import tftp://192.168.0.1/netbox.img
    Connecting to 192.168.0.1 (192.168.0.1:69)
    netbox.img      100% |***************************| 5544k  0:00:00 ETA
    OK
    example:/#> show app image
    NAME              VERSION           DESCRIPTION
    netbox            2020.02-r0        NetBox - The Networking Toolbox

## Application Configuration

Our application needs three files backed by persistent storage:

- `app-interfaces`: For BusBox’s version of ifupdown to configure our local VLAN interfaces
- `app-sysctl.conf`: For enabling IP forwarding on startup
- `app-fw.nft`: Configuration for nftables

Create the files on external media with the following content:

app-interfaces

    auto lo
    iface lo inet loopback

    auto vlan1
    iface vlan1 inet static
        address 192.168.1.1
        netmask 255.255.255.0
        pre-up ip link set dev eth0 up
        pre-up ip link add dev vlan1 link eth0 type vlan id 1

    auto vlan2
    iface vlan2 inet static
        address 192.168.2.1
        netmask 255.255.255.0
        pre-up ip link set dev eth0 up
        pre-up ip link add dev vlan2 link eth0 type vlan id 2

    auto wan
    iface wan inet dhcp
    pre-up nft -f /etc/fw.nft

app-sysctl.conf

    net.ipv4.ip_forward=1

app-fw.nft

    flush ruleset

    table filter {
        chain input {
            type filter hook input priority 0; policy drop;

            iif lo accept
            goto common
        }

        chain forward {
            type filter hook forward priority 0; policy drop;

            iif vlan1 accept
            iif vlan2 accept
            goto common
        }

        chain common {
            ct state invalid drop
            # Always allow the return traffic related to flows that where
            # initiated by a local host.
            ct state established,related accept
            meta l4proto icmp accept
        }

        chain output {
            type filter hook output priority 0; policy accept;
        }

        chain postrouting {
            type nat hook postrouting priority 0;
            # Hide local addresses for traffic going out over the Internet.
            oifname wan masquerade
        }
    }

The nftables configuration above is an example of a very basic masquerading firewall that allows all outgoing connections and the generated return traffic. Edit the configuration to suit your preferences.

## WeOS Configuration

Now that we’ve imported the image, we’re ready to configure our application instance and connect it to the WeOS networking stack:

    example:/#> configure app fw0 netbox
    example:/config/app-fw0/#> share port eth4 as wan
    example:/config/app-fw0/#> share path /usb/app-interfaces as /etc/network/interfaces
    example:/config/app-fw0/#> share path /usb/app-sysctl.conf as /etc/sysctl.conf create
    example:/config/app-fw0/#> share path /usb/app-app-fw.nft as /etc/fw.nft create
    example:/config/app-fw0/#> show
    Name         : fw0
    Description  :
    Image        : netbox
    Init cmd     : /sbin/init

    Shared Resources
    TYPE  HOST              GUEST             OPTS
    port  eth4              wan
    veth  fw0               eth0
    example:/config/app-fw0/#> end
    example:/config/#>

Note that since our setup matches the default veth pair created by WeOS, we only have to claim `eth4` for our application.

Now we setup our VLANs, ensuring that `fw0` is a tagged member of both VLANs:

    example:/config/#> vlan 1
    example:/config/vlan-1/#> untagged eth1
    example:/config/vlan-1/#> tagged eth3,fw0
    example:/config/vlan-1/#> end
    example:/config/#> vlan 2
    example:/config/vlan-2/#> untagged eth2
    example:/config/vlan-2/#> tagged eth3,fw0
    example:/config/vlan-2/#> end
    example:/config/#> iface vlan1
    example:/config/iface-vlan1/#> inet static 192.168.1.2/24
    example:/config/iface-vlan1/inet-static-192.168.1.2/#> end
    example:/config/iface-vlan1/#> end
    example:/config/#> iface vlan2
    example:/config/iface-vlan2/#> inet static 192.168.2.2/24
    example:/config/iface-vlan2/inet-static-192.168.2.2/#> end
    example:/config/iface-vlan2/#> end

Finally, we’ll configure WeOS to act as a DHCP server on VLAN 1 and 2, making sure to advertise our application as being the default gateway; also add a default route to the application for the local device:

    example:/config/#> dhcp-server
    example:/config/dhcp-server/#> subnet 192.168.1.0/24
    example:/config/dhcp-server/subnet-192.168.1.0/#> gateway 192.168.1.1
    example:/config/dhcp-server/subnet-192.168.1.0/#> name-server 8.8.8.8
    example:/config/dhcp-server/subnet-192.168.1.0/#> end
    example:/config/dhcp-server/#> subnet 192.168.2.0/24
    example:/config/dhcp-server/subnet-192.168.2.0/#> gateway 192.168.2.1
    example:/config/dhcp-server/subnet-192.168.2.0/#> name-server 8.8.8.8
    example:/config/dhcp-server/subnet-192.168.2.0/#> leave
    example:/config/dhcp-server/subnet-192.168.2.0/#> end
    example:/config/dhcp-server/#> end
    example:/config/#> ip
    example:/config/ip/#> route default 192.168.1.1
    example:/config/ip/#> route default 192.168.2.1
    example:/config/ip/#> leave
    example:/#> copy running-config startup-config

## Connectivity Test

Now we’re ready to attach to our application verify connectivity:

    example:/#> app attach fw0
    Type  to exit the console,  to enter Ctrl+a itself

    Netbox - The Networking Toolbox
    netbox login: root
    #

We should be able to reach WeOS on both VLANs as well as external resources on the Internet:

    # ifup -a
    ifup: interface lo already configured
    # ip -br addr
    lo               UNKNOWN        127.0.0.1/8 ::1/128
    gre0@NONE        DOWN
    gretap0@NONE     DOWN
    erspan0@NONE     DOWN
    ip_vti0@NONE     DOWN
    ip6tnl0@NONE     DOWN
    vlan1@eth0       UP             192.168.1.1/24 fe80::144a:32ff:fe1f:6eb/64
    vlan2@eth0       UP             192.168.2.1/24 fe80::144a:32ff:fe1f:6eb/64
    wan@gretap0      UP             198.18.221.120/24 fe80::207:7cff:fe65:f844/64
    eth0@if21        UP             fe80::144a:32ff:fe1f:6eb/64
    # ping -c1 192.168.1.2
    PING 192.168.1.2 (192.168.1.2): 56 data bytes
    64 bytes from 192.168.1.2: seq=0 ttl=64 time=0.181 ms

    --- 192.168.1.2 ping statistics ---
    1 packets transmitted, 1 packets received, 0% packet loss
    round-trip min/avg/max = 0.181/0.181/0.181 ms
    # ping -c1 192.168.2.2
    PING 192.168.2.2 (192.168.2.2): 56 data bytes
    64 bytes from 192.168.2.2: seq=0 ttl=64 time=0.266 ms

    --- 192.168.2.2 ping statistics ---
    1 packets transmitted, 1 packets received, 0% packet loss
    round-trip min/avg/max = 0.266/0.266/0.266 ms
    # ping -c1 8.8.8.8
    PING 8.8.8.8 (8.8.8.8): 56 data bytes
    64 bytes from 8.8.8.8: seq=0 ttl=52 time=4.923 ms

    --- 8.8.8.8 ping statistics ---
    1 packets transmitted, 1 packets received, 0% packet loss
    round-trip min/avg/max = 4.923/4.923/4.923 ms
    #