wifibox-alpine
—
wifibox based on Alpine Linux
The implementation of the
wifibox(8)
embedded wireless router is based on the use of a Linux-based guest
operating system which can communicate with the host's wireless network card
on behalf of the host. In order to meet the requirements of this setup, this
has to be a system with a low resource footprint and easy to manage.
This solution is derived from Alpine Linux, which is an
actively maintained, security-oriented, lightweight distribution, based on
musl libc and
busybox. For more information and introduction to the
tools that are going to be used in the sections below, please visit the
following sites:
- Alpine Linux: https://alpinelinux.org/
- BusyBox: https://busybox.net/
- OpenRC: http://www.gentoo.org/proj/en/base/openrc/
- iptables:
https://www.netfilter.org/projects/iptables/index.html
- dhcpcd: https://roy.marples.name/projects/dhcpcd
- radvd: https://radvd.litech.org/
- iw: https://wireless.wiki.kernel.org/en/users/documentation/iw
- wpa_supplicant: https://w1.fi/wpa_supplicant/
- hostapd: https://w1.fi/hostapd/
- mDNSResponder:
https://opensource.apple.com/source/mDNSResponder/
- socat: http://www.dest-unreach.org/socat/
- tcpdump: https://www.tcpdump.org/
The guest is created with a root user, which is
associated with a blank password. This can only be used to login to the
guest via the console
command of
wifibox(8),
no other services are configured for remote access.
Although the root user possesses unlimited
access to every resource inside the guest, files might not be changed in
every case. That is because the operating system is built in a way that it
does not require any write access to the contents of the root file system.
In addition to that, all the contents of the disk image is stored in a
compressed format via SquashFS and uncompressed to memory only on demand.
Everything that needs to be modified during the guest's run time is stored
on dedicated file systems that are either memory-backed or shared with the
host.
The image can host either wpa_supplicant for
connecting to wireless networks, or hostapd for creating
wireless access points, depending how it was built. In addition to that, a
combination of dhcpcd and radvd could be
used to support IPv6 traffic, mDNSResponder could be
deployed to handle multicast DNS requests, and forwarding
could be configured to pass traffic between originally isolated inner and
outer networks, such as UDP broadcasts. For packet analysis,
tcpdump is provided as an optional component. Each
application-specific detail is going to be included below.
For ease of management, the host shares configuration files with
the services that are responsible for implementing the domain logic. On the
host, all the files are stored under
/usr/local/etc/wifibox with additional
subdirectories inside.
The appliance subdirectory
holds the generic configuration files. On the guest, they are visible on the
/media/etc directory where the
config 9P (VirtFS)
share is mounted in read-only mode.
- forwarding
works with the appliance/forwarding.conf file. It
uses the syntax of the socat address specifications but
it is limited to work with UDP and TCP ports only. Note that this is an
optional component, and its presence depends on the configuration of the
guest image. The respective configuration file on the guest is
/media/etc/forwarding.conf, which is used directly
from this location.
- hostname
sets the hostname on boot from the
applicance/hostname file. This is the name that is
going to be visible for others on the local network. Changing the hostname
requires updating this file and restarting the guest. The configuration
file shows up on the guest as /media/etc/hostname,
which is mapped to /etc/hostname, and used
verbatim.
- ifup and
ifdown
work with the appliance/interfaces.conf file to
associate the internal network interfaces with IP addresses:
wlan0 is the wireless device and eth0
is the virtual Ethernet device towards the host which are both configured
according to the contents of the configuration file. On the guest, this is
/media/etc/interfaces.conf, which is directly
included as part of /etc/network/interfaces.
- iptables
works with the appliance/iptables file and it is
responsible for moving network packets (Network Address Translation, NAT)
between the eth0 and wlan0 interfaces.
The configuration file describes the flow of the network packets through
the interfaces. Using /media/etc/iptables
directly, it is loaded once at launching the respective service, usually
on boot, and cannot be modified from the guest.
- ip6tables
is the IPv6-enabled version of iptables which uses the
appliance/ip6tables configuration file. Its
purpose is exactly the same as for its sibling, it bridges the
eth0 and wlan0 networking interfaces
with the help of NAT. On the guest,
/media/etc/ip6tables is used directly in this
case.
- mDNSResponder
works with the appliance/mdnsd-services.conf file
and it can handle multicast DNS query packets on UDP port 5353. The
advertised services can be described by its configuration file so that
others on the network could see them. Note that this is optional
component, and its presence depends on the configuration options of the
guest image. On the guest, the
/media/etc/mdnsd-services.conf configuration file
is used directly.
- udhcpd
works with the appliance/udhcpd.conf file and it
can implement a DHCP server for either eth0 or
wlan0 so that it can hand out IP addresses in a given
range for the host (wpa_supplicant) or the clients on
the wireless network (hostapd), and can set itself the
default gateway for forwarding the network traffic. It also manages the
distribution of information about the name servers, in cooperation with
udhcpc (DHCP client) when required. This is utilized
only when dynamic IP addresses are in use. On the guest, the configuration
file becomes /media/etc/udhcpd.conf, which is used
to generate /etc/udhcpd.conf that
udhcpd will eventually read.
- dhcpcd
is an alternative to udhcpc and it is used only when
IPv6 is optionally configured. In that case, it takes over the role of
udhcpc and manages both IPv4 and IPv6 addresses. It
works with the appliance/dhcpcd.conf file which
often holds only a handful of overrides for the default options because
otherwise they work well. dhcpcd is pre-configured to
automatically keep udhcpd updated about name servers and
it is employed only for wpa_supplicant. The
corresponding file on the guest is
/media/etc/dhcpcd.conf, which is mapped to
/etc/dhcpcd.conf.
- radvd
works with the appliance/radvd.conf configuration
file and this is the IPv6 Routing Advertisement Daemon that implements the
routing functionality in case IPv6 is enabled. It sends Router
Advertisement messages, specified by RFC 2461, towards the host
(wpa_supplicant) or the clients
(hostapd), and sending a Router Solicitation message
when requested. These messages are required for IPv6 stateless
autoconfiguration (SLAAC). The corresponding configuration file on the
guest is /media/etc/radvd.conf, which is mapped to
/etc/radvd.conf.
- uds_passthru
is an optional service for managing the forwarding of control sockets
created for either wpa_supplicant or
hostapd. It works with the
appliance/uds_passthru.conf file, which is
optional, and when it is present, it automatically implies that the
service is enabled. The contents describe what sockets should be exposed
over configured TCP ports with the help of socat, which
a heavily stripped-down version of the original tool to minimize the
related security risks. On the guest, the path of the configuration file
is /media/etc/uds_passthru.conf, from where it is
used.
Depending on the configuration, either the
wpa_supplicant or hostapd
subdirectory holds the configuration files that are used by either
wpa_supplicant or hostapd, respectively.
On the guest, they are published under the paths
/etc/wpa_supplicant and
/etc/hostapd where the
app_config 9P
(VirtFS) share is mounted as read-write. This will let
wpa_supplicant or hostapd change the
contents when instructed to do so from the host through the forwarded
control sockets and permitted by the configuration.
wpa_supplicant works with the
wpa_supplicant/wpa_supplicant.conf file, while
hostapd works with the
hostapd/hostapd.conf file. These are the same tools
that are used in the FreeBSD base system for the
same purpose, and their Linux version is utilized here to make it possible
to reuse the configuration files of the same format from the host.
The variable data files under the guest's
/var directory are shared with the host by mounting
the var 9P (VirtFS)
share there. This includes streaming out all the logs under the
/var/log directory, such as
/var/log/dmesg or
/var/log/messages so that the internal state of the
guest can be tracked by accessing these files on the host per the
configuration of
wifibox.
The contents of the /var/run directory will not be
visible on the host, as it is stored only in the memory.
Further components of the guest that are not directly configurable
or visible to the outside:
- Version 6.12 (LTS) of the Linux kernel and its wireless drivers are used
to communicate with exposed hardware. It does not always work with the
latest ones, see the section on supported hardware for the exact details.
Alternatively, it is possible to configure the image to have Linux 6.13
(stable) which could be suitable for testing experimental features and
drivers.
- busybox
is a combination of tiny versions of the common UNIX utilities, including
the ash
shell itself, shipped in a single small executable. It provides the
execution environment for all the scripts and services. All the irrelevant
modules were removed for security hardening.
- The base layout of the Alpine system is stripped down to the bare
minimum, and for example, the guest does not have the
apk package manager
installed since it would not be able to work. Instead, the disk image
itself should be constructed in a way that it includes all the needed
applications.
Every service running on the guest can be managed by the
rc-service
(locate and run OpenRC service) command, which is going to be used in this
section. The list of actively managed services can be learned as
follows.
The status of a specific service can be queried by the
status
command. For example, the
wpa_supplicant tool has its own associated service and it
can be checked by the following command.
# rc-service wpa_supplicant status
Similarly to this, the
start
, stop
, and
restart
commands are available as well to start,
stop, or restart the given service, respectively. In the example below,
consider re-initializing all the network interfaces by restarting the
networking
service.
# rc-service networking restart
These commands can help with troubleshooting and restoring the
respective services in case of failures.
The network packet filtering rules are managed by the
iptables and ip6tables services, which
need to be restarted so that the changes in either the
iptables or the ip6tables
file can take effect. For example, in case of
iptables:
# rc-service iptables restart
The active set of rules can be queried by the following
command.
Rules can be dynamically added, deleted, inserted, replaced, and
flushed through the corresponding commands of the iptables
utility, see its documentation for the details. The current state of the
configuration can be recorded by dumping it to temporary file under a
directory which is shared with the host, that is
/var/tmp in this case.
# iptables-save > /var/tmp/iptables
The file exported this way could be then used as the main
configuration by moving it under the
/usr/local/etc/wifibox/appliance directory on the
host, as discussed above.
The same set of commands apply for
ip6tables, where
iptables-save
has to be written as
ip6tables-save.
To verify the flow of network traffic, the
iptables or the ip6tables (for IPv6)
utility can be asked to list the rules in a more verbose manner. This will
include the number of packets that matched each of the rules, so their
effect becomes observable. For example, in case of
iptables:
For finding the right configuration parameters for the rules of
network packet filtering, it is possible to additionally install the
tcpdump utility. It can be used to capture all the packets
that are flowing through all the networking interfaces and determine the
proper IP addresses and ports. When invoked without any parameters, it will
start dumping all the traffic-related information to the standard output.
For all the features and options, please consult the documentation.
Mind that this facility is not available by default, the guest
image has to be explicitly configured to include this as it is a security
risk. For the same reason, its removal is recommended once the analysis is
concluded.
By design, UDP packets are not meant to passed between the
eth0 and wlan0 interfaces which may
cause certain applications to fail to work. A possible way to address this
shortcoming is to deploy the proper handlers to the user space and configure
iptables to use them. This can be requested by the
RETURN
target, which can be inserted in the
PREROUTING
chain for the NAT rules. For example, in case of
mDNSResponder, the packet filtering rules have to
explicitly be configured to pass every UDP packet on port 5353 to the
application for further processing.
-A PREROUTING -p udp --dport 5353 -j RETURN
For other similar uses, the forwarding service
can be set up and the ports that are forwarded that way could be linked to
the network packet filtering logic in the same manner.
Details of wireless configuration can be learned through the use
of the iw
tool, which is suitable for showing and manipulating wireless devices and
their configuration. For example, it can list the device capabilities, such
as band information (2.4 GHz and 5 GHz), and 802.11n information.
Scanning can be initiated as follows. There,
wlan0 is the name of the wireless networking device, which
can be considered constant.
Wireless events can be traced with the
event
command. In the related example below, the
-f
and -t
flags are added to
show full frames for auth/assoc/deauth/disassoc as well as the timestamps
for each event.
To determine if there is an active connection to an Access Point
and further related information can be displayed by the
link
command.
More details can be collected by the station
dump
command.
# iw dev wlan0 station dump
Sometimes it happens that even if the driver has successfully
detected the wireless device, it is not yet ready to be used. That is
because the use of the device might be blocked either by software or
hardware means i.e., by a physical switch. The image contains the
rfkill tool as part of BusyBox to unblock the wireless
device. Use the
list
command to see if rfkill is usable and list the available
interfaces.
If the interface is shown to be blocked, use the
unblock command
to unblock it. This can be done either by function or index.
Or:
Note that “hard” block status cannot be changed this
way, as it is typically performed by the hardware switch or it is
implemented by the firmware itself. For example, the computer might be
configured to turn off the wireless device when the wired networking
interface card is active and the LAN cable is inserted.
There are a number of Linux drivers available as kernel modules.
Note that not all of them could be used immediately because there might be
additional, often proprietary firmware files have to be placed under
/lib/firmware for activation.
A list of wireless cards supported by the drivers is as follows.
The kernel modules that depend on specific firmware files are marked by name
at the end of each entry, otherwise they should be working. The availability
of those auxiliary files is a function of how the corresponding
FreeBSD port is configured. Some of them might be
included for certain package flavors only or disabled by default and has to
be explicitly configured and built by the user due to licensing
restrictions. Note that this list might not be accurate and included here
for information only.
- ADMTek/Infineon AMD8211A
-
- ADMTek/Infineon AMD8211B
-
- ADMTek/Infineon AMD8211C
-
- Atmel at76c506 [atmel]
-
- Broadcom BCM4301 [b43legacy]
-
- Broadcom BCM4306/2 [b43legacy]
-
- Broadcom BCM4306/3 [b43legacy]
-
- Broadcom BCM4311 [b43, wl]
-
- Broadcom BCM4312 [b43, wl]
-
- Broadcom BCM4313 [brcm, wl]
-
- Broadcom BCM43131 [wl]
-
- Broadcom BCM43142 [wl]
-
- Broadcom BCM4318 [b43]
-
- Broadcom BCM4321 [wl]
-
- Broadcom BCM43217 [b43, wl]
-
- Broadcom BCM4322 [b43, wl]
-
- Broadcom BCM43222 [b43, wl]
-
- Broadcom BCM43224 [b43, brcm, wl]
-
- Broadcom BCM43225 [b43, brcm, wl]
-
- Broadcom BCM43227 [b43, wl]
-
- Broadcom BCM43228 [b43, wl]
-
- Broadcom BCM4331 [b43, wl]
-
- Broadcom BCM4352 [wl]
-
- Broadcom BCM4358 [brcm]
-
- Broadcom BCM4360 [wl]
-
- Broadcom BCM43602 [brcm]
-
- Broadcom BCM4365 [brcm]
-
- Broadcom BCM4366 [brcm]
-
- Cisco Aironet 350 Series PCI-351
-
- Cisco Aironet 350 Series PCI-352
-
- Intel(R) PRO/Wireless 2100 [ipw2100]
-
- Intel(R) PRO/Wireless 2200/2915 [ipw2200]
-
- Intel(R) PRO/Wireless 3945ABG/BG [iwl3945]
-
- Intel(R) Wireless WiFi 4965 [iwl4965]
-
- Intel(R) Centrino(R) Wireless-N 1000 [iwlwifi]
-
- Intel(R) Centrino(R) Wireless-N 1030 [iwlwifi]
-
- Intel(R) Centrino(R) Wireless-N 100 [iwlwifi]
-
- Intel(R) Centrino(R) Wireless-N 105 [iwlwifi]
-
- Intel(R) Centrino(R) Wireless-N 130 [iwlwifi]
-
- Intel(R) Centrino(R) Wireless-N 135 [iwlwifi]
-
- Intel(R) Centrino(R) Wireless-N 2200 [iwlwifi]
-
- Intel(R) Centrino(R) Wireless-N 2230 [iwlwifi]
-
- Intel(R) Centrino(R) Ultimate-N 5100 [iwlwifi]
-
- Intel(R) Centrino(R) Ultimate-N Wi-Fi Link 5300 [iwlwifi]
-
- Intel(R) Centrino(R) WiMAX/Wi-Fi Link 5350 [iwlwifi]
-
- Intel(R) Centrino(R) Advanced-N + WiMAX 6150 [iwlwifi]
-
- Intel(R) Centrino(R) Advanced-N 6200 [iwlwifi]
-
- Intel(R) Centrino(R) Advanced-N 6205 [iwlwifi]
-
- Intel(R) Centrino(R) Advanced-N 6230 [iwlwifi]
-
- Intel(R) Centrino(R) Advanced-N 6235 [iwlwifi]
-
- Intel(R) Centrino(R) Advanced-N + WiMAX 6250 [iwlwifi]
-
- Intel(R) Centrino(R) Ultimate-N 6300 [iwlwifi]
-
- Intel(R) Wireless 3160 [iwlwifi]
-
- Intel(R) Wireless 7260 [iwlwifi]
-
- Intel(R) Wireless 7265 [iwlwifi]
-
- Intel(R) Wireless-AC 3165 [iwlwifi]
-
- Intel(R) Wireless-AC 3168 [iwlwifi]
-
- Intel(R) Wireless-AC 8260 [iwlwifi]
-
- Intel(R) Wireless-AC 8265 [iwlwifi]
-
- Intel(R) Wireless-AC 9260 [iwlwifi]
-
- Intel(R) Wireless-AC 9461 [iwlwifi]
-
- Intel(R) Wireless-AC 9462 [iwlwifi]
-
- Intel(R) Wireless-AC 9560 [iwlwifi]
-
- Intel(R) Wi-Fi 6 AX200 [iwlwifi]
-
- Intel(R) Wi-Fi 6 AX201 [iwlwifi]
-
- Intel(R) Wi-Fi 6 AX210 [iwlwifi]
-
- Intel(R) Wi-Fi 6 AX211 [iwlwifi]
-
- Marvell 88W8363 [marvell]
-
- Marvell 88W8366 [marvell]
-
- Marvell 88W8387 [marvell]
-
- Marvell 88W8764 [marvell]
-
- Marvell 88W8766 [marvell]
-
- Marvell 88W8897 [marvell]
-
- MediaTek MT7603E [mediatek]
-
- MediaTek MT7610E [mediatek]
-
- MediaTek MT7612/MT7602/MT7662 [mediatek]
-
- MediaTek MT7615 [mediatek]
-
- MediaTek MT7622 [mediatek]
-
- MediaTek MT7628 [mediatek]
-
- MediaTek MT7630E [mediatek]
-
- MediaTek MT7663 [mediatek]
-
- MediaTek MT7915 [mediatek]
-
- MediaTek MT7921 (AMD RZ608 Wi-Fi 6E) [mediatek]
-
- MediaTek MT7925 [mediatek]
-
- MediaTek MT7990 [mediatek]
-
- MediaTek MT7991 [mediatek]
-
- MediaTek MT7992 [mediatek]
-
- MediaTek MT799A [mediatek]
-
- Qualcomm Atheros AR2413
-
- Qualcomm Atheros AR2414
-
- Qualcomm Atheros AR2415
-
- Qualcomm Atheros AR2417
-
- Qualcomm Atheros AR2423/4
-
- Qualcomm Atheros AR2425
-
- Qualcomm Atheros AR2427
-
- Qualcomm Atheros AR5210
-
- Qualcomm Atheros AR5211
-
- Qualcomm Atheros AR5212
-
- Qualcomm Atheros AR5213
-
- Qualcomm Atheros AR5214
-
- Qualcomm Atheros AR5416
-
- Qualcomm Atheros AR5418
-
- Qualcomm Atheros AR9102
-
- Qualcomm Atheros AR9103
-
- Qualcomm Atheros AR9160
-
- Qualcomm Atheros AR9220
-
- Qualcomm Atheros AR9223
-
- Qualcomm Atheros AR9227
-
- Qualcomm Atheros AR9280
-
- Qualcomm Atheros AR9281
-
- Qualcomm Atheros AR9285
-
- Qualcomm Atheros AR9287
-
- Qualcomm Atheros AR9331
-
- Qualcomm Atheros AR9340
-
- Qualcomm Atheros AR9380
-
- Qualcomm Atheros AR9382
-
- Qualcomm Atheros AR9462
-
- Qualcomm Atheros AR9485
-
- Qualcomm Atheros AR9550
-
- Qualcomm Atheros AR9565
-
- Qualcomm Atheros AR9580
-
- Qualcomm Atheros IPQ4018 [ath10k]
-
- Qualcomm Atheros IPQ8074 [ath11k]
-
- Qualcomm Atheros IPQ6018 [ath11k]
-
- Qualcomm Atheros QCA2062 [ath11k]
-
- Qualcomm Atheros QCA2066 [ath11k]
-
- Qualcomm Atheros QCA6174 / QCA6174A [ath10k]
-
- Qualcomm Atheros QCA6390 [ath11k]
-
- Qualcomm Atheros QCA6391 [ath11k]
-
- Qualcomm Atheros QCA6698QA [ath11k]
-
- Qualcomm Atheros QCA9337 [ath10k]
-
- Qualcomm Atheros QCA9880 [ath10k]
-
- Qualcomm Atheros QCA9882 [ath10k]
-
- Qualcomm Atheros QCA9886 [ath10k]
-
- Qualcomm Atheros QCA9888 [ath10k]
-
- Qualcomm Atheros QCA9890 [ath10k]
-
- Qualcomm Atheros QCA9892 [ath10k]
-
- Qualcomm Atheros QCA9984 [ath10k]
-
- Qualcomm Atheros QCN62xx [ath10k]
-
- Qualcomm Atheros QCN9074 [ath11k]
-
- Qualcomm Atheros QCN9274 [ath12k]
-
- Qualcomm Atheros WCN6855 [ath11k]
-
- Qualcomm Atheros WCN7850 [ath12k]
-
- Quantenna QSR10G
-
- Ralink RT2460 [rt61]
-
- Ralink RT2560 [rt61]
-
- Ralink RT2501/RT2561/RT2561S (RT61) [rt61]
-
- Ralink RT2600/RT2661 (RT61) [rt61]
-
- Ralink RT2760 [rt61]
-
- Ralink RT2790 [rt61]
-
- Ralink RT2800 [rt61]
-
- Ralink RT2860 [rt61]
-
- Ralink RT2890 [rt61]
-
- Ralink RT3052 [rt61]
-
- Realtek 8180 [rtlwifi]
-
- Realtek 8185 [rtlwifi]
-
- Realtek 8187SE [rtlwifi]
-
- Realtek 8188EE [rtlwifi]
-
- Realtek 8192EE [rtlwifi]
-
- Realtek 8192C/8188C [rtlwifi]
-
- Realtek 8192S/8191S [rtlwifi]
-
- Realtek 8192DE [rtlwifi]
-
- Realtek 8703B [rtw88]
-
- Realtek 8723BE [rtw88]
-
- Realtek 8723D [rtw88]
-
- Realtek 8723DE [rtw88]
-
- Realtek 8723E [rtw88]
-
- Realtek 8812A [rtw88]
-
- Realtek 8814A [rtw88]
-
- Realtek 8814AE [rtw88]
-
- Realtek 8821A [rtw88]
-
- Realtek 8821C [rtw88]
-
- Realtek 8821CE [rtw88]
-
- Realtek 8822B [rtw88]
-
- Realtek 8822BE [rtw88]
-
- Realtek 8822C [rtw88]
-
- Realtek 8822CE [rtw88]
-
- Realtek 8821C [rtw88]
-
- Realtek 8821CE [rtw88]
-
- Realtek 8821C [rtw88]
-
- Realtek 8821CE [rtl8821ce]
-
- Realtek 8822BE [rtw88]
-
- Realtek 8822C [rtw88]
-
- Realtek 8822CE [rtw88]
-
- Realtek 8851B [rtw89]
-
- Realtek 8851BE [rtw89]
-
- Realtek 8852A [rtw89]
-
- Realtek 8852AE [rtw89]
-
- Realtek 8852B [rtw89]
-
- Realtek 8852BE [rtw89]
-
- Realtek 8852BT [rtw89]
-
- Realtek 8852BTE [rtw89]
-
- Realtek 8852C [rtw88]
-
- Realtek 8852CE [rtw89]
-
- Realtek 8922A [rtw89]
-
- Realtek 8922AE [rtw89]
-
- Texas Instruments WL1271/3 [ti]
-
- Texas Instruments WL1281/3 [ti]
-
Certain vendors may assign different PCI IDs for their rebranded
products even if they ship exactly the same chipset. For example, AMD RZ608
is technically the same as MediaTek MT7921, but its PCI ID had to be
explictly added for the corresponding driver to make it work. Similar
situations may occur any time, please let us know if this happens.