Skip to main content

NIST BRSKI demo setup

The server device for the NIST BRSKI demo has the following requirements:

  • Capability for two independent WiFi APs

The client devices must have the following requirements:

  • Capability for WiFi STA that can connect to the WiFi APs
  • USB Ethernet Gadget mode connectivity

For the BRSKI demo, we're setting up a Raspberry Pi 4B running Ubuntu 22.04 server edition called nqm-britannic-brski. For the two WiFi APs, we're using two Ralink RT5370 USB adapters. That then connects to two Ubuntu 22.04 clients using a USB-C hub, which are both acting a USB Ethernet devices.

Physical setup​

Parts​

  • 1x Powered USB-C hub
    • 1x Powered USB-C hub Power Supply + IEC C13 cable.
      • Todo, buy an IEC C13 US cable, or get a UK to US power adapter.
  • 3x Raspberry Pi 4Bs:
    • nqm-brittanic-brski (server)
    • nqm-benign-brski (client)
    • nqm-biddable-brski (client)
  • 1x Raspberry Pi Power supply unit
    • Maybe bring one with a US plug?
  • 2x USB-C to USB-C cables (ideally capable of 5V 3A)
  • 1x USB-C to USB-A cable (ideally USB-3.0 for higher speed, and capable of 5V 3A)
  • 1x RJ45 Ethernet cable
  • 2x USB-A WiFi AP adapters

Connections​

SSH Connection through brittanic brski​

Only nqm-britannic-brski is directly connected to the network.

If you want to SSH into nqm-benign-brski or nqm-biddable-brski, you must use ssh 192.168.48.1 -J nqm-britannic-brski.local (use the IP address, since mDNS does not work for some reason).

Setup​

Configuring USB-C connection​

The Raspberry Pi Model 4B supports USB Gadget mode, which can be used to communicate from one Pi to another Pi without the usage of a router and switch.

Some of this guide is adapted from the steps in https://lozworld.com/lozwords/raspberry-pi-4b-as-an-ubuntu-2110-usb-gadget-tethered-to-an-ipad-pro.

Host​

The Raspberry Pi 4B's USB-C connector does NOT support DRD (Dual-Role-Data). This means that if you use a USB-C to USB-C cable, the Raspberry Pi 4B can only be peripheral/UFP (upstream-facing port).

There is support for USB 2.0 OTG (USB On-The-Go) in host-mode, but it requires that you use a USB-C to USB-A/USB-B adapter.

USB-C to USB-C only works as a periperal.

Because of this, to connect the Raspberry Pi 4B to a USB-C hub as a host, you must plug the hub into one of the Raspberry Pi 4B's USB-A ports.

See RPi 4 USB-C socket as host - Raspberry Pi Forums and Texas Instruments. Transition Existing Products from USB 2.0 OTG to USB Type-CTM for more info.

Client USB-C Ethernet​

The Raspberry Pi 4B's USB-C connector can be used in peripheral/UFP (upstream-facing port) mode.

Enabling USB peripheral mode in /boot/firmware/config.txt​

In /boot/firmware/config.txt, add the following line, to turn the Raspberry Pi 4B into a USB gadget:

[cm4]
# Enable the USB2 outputs on the IO board (assuming your CM4 is plugged into
# such a board)
dtoverlay=dwc2,dr_mode=peripheral

Place it in the [cm4] section if it exists.

Make the Raspberry Pi a USB Gadget Ethernet using /boot/firmware/cmdline.txt​

In /boot/firmware/cmdline.txt, add

modules-load=dwc2,g_ether g_ether.dev_addr=e6:5f:01:00:48:01 g_ether.host_addr=e6:5f:01:00:48:02

between rootwait and fixrtc, in order to enable the g_ether Linux kernel module.

This makes a new interface called usb0 on the Raspberry Pi, and makes the Raspberry Pi 4B act like a USB Ethernet adapter. On the device side, the MAC address is given by g_ether.dev_addr, while on the host side, it will be g_ether.host_addr.

Important, make sure that the second character of your MAC address is one of 2/6/a/e (e.g. x6:00:00:00:00:00), as this is the Local bit in RFC5342 § 2.1.

Give usb0 a static IP address​

Make a new file called /etc/netplan/51-usb0.yaml with contents:

# Setup a static IP address for the USB ethernet gadget mode
# See https://github.com/nqminds/nist-brski
network:
# only set static IP addresses here
# The DHCP server we create manually using dnsmasq
ethernets: # treat these as ethernet devices
usb0:
dhcp4: false # we use a static IP
optional: true
addresses: [192.168.48.1/29]

Make sure that the static IP address is unique.

Setup dnsmasq on usb0 only using /etc/default/dnsmasq.usb0​

Install dnsmasq, then disable it using:

sudo apt install dnsmasq
sudo systemctl disable dnsmasq.service

Then, make a /etc/default/dnsmasq.usb0 file with the following contents (change the IP address)

DNSMASQ_EXCEPT="lo"
DNSMASQ_INTERFACE='usb0'
DNSMASQ_OPTS='--bind-interfaces --dhcp-option=3 --dhcp-range=192.168.48.2,192.168.48.6,255.255.255.248,1h'

Finally, you can start dnsmasq using:

systemctl start dnsmasq@usb0.service

and do enable the service (so that it runs automatically on boot) using:

systemctl enable dnsmasq@usb0.service
Blacklisting cdc_subset​

Add blacklist cdc_subset to /etc/modprobe.d/blacklist.conf on the host.

For some reason, the cdc_subset kernel module sometimes takes precendence over cdc_ether. However, cdc_subset ignores the MAC address of our USB Ethernet device, which breaks our network config, see https://github.com/raspberrypi/firmware/issues/843#issuecomment-1597841959.

# unlike cdc_ether, cdc_subset seems to be ignoring the really nice MAC
# addresses we setup. blacklist it so the kernel always uses cdc_ether instead.
blacklist cdc_subset

Configuring APs​

On Ubuntu 22.04:

  • Install hostapd and dnsmasq with sudo apt install hostapd dnsmasq
    • Disable the automatically enabled dnsmasq.service with: sudo systemctl disable dnsmasq.service
  • If using the Ralink Technology, Corp. RT5370 Wireless Adapter, on Ubuntu, you must install the following package to get the binary blobs for the module:
    • linux-modules-extra-raspi

Configuring static IPs​

Ubuntu 22.04 Server uses netplan to setup network options.

Since netplan v0.105's wifis access-points.mode property only supports ap if using NetworkManager, we cannot use netplan to control our HostAP access points.

However, it's still the easiest way to setup a static IP address for our AP interfaces.

To do this, make a new file called /etc/netplan/51-brski.yaml, with the contents like:

network:
# only set static IP addresses here
# The access point we create manually using hostapd
# The DHCP server we create manually using dnsmasq
ethernets: # treat these as ethernet devices
wlx1cbfce699b7f:
addresses:
- "192.168.16.1/24"
wlx1cbfce651dc4:
addresses:
- "192.168.17.1/24"

# USB Ethernet Gadget mode
# (aka client Raspberry Pi 4)
enxe45f01053833:
dhcp4: true # find IP address automatically
optional: true
enxe45f0105389e:
dhcp4: true # find IP address automatically
optional: true
version: 2

Configuring hostapd​

For each interface (%i), make a file called /etc/hostapd/%i.conf:

For the secure AP, /etc/hostapd/wlx1cbfce651dc4.conf use:

# AP netdevice name (without 'ap' postfix, i.e., wlan0 uses wlan0ap for
# management frames); ath0 for madwifi
interface=%i # replace the interface with the proper interface name

##### IEEE 802.11 related configuration #######################################
# SSID to be used in IEEE 802.11 management frames
ssid2="nqm-britannic-brski"

# Enable IEEE 802.11n 2.4 GHz
hw_mode=g
ieee80211n=1
# Ralink RT5370 supports 40 MHz bandwidth, see datasheet
ht_capab=[SHORT-GI-40][HT40+][HT40-]

# Ralink RT5370 doesn't seem to support ACS, so we need to manually pick channel
channel=11

auth_algs=3
wmm_enabled=1

##### WPA/IEEE 802.11i configuration ##########################################
wpa=2
# wpa_psk=000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
wpa_passphase=raspiwlan
# WPA-PSK = WPA-Personal / WPA2-Personal
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP

For the unsecure/open AP, you can use a config like /etc/hostapd/wlx1cbfce699b7f.conf:

# AP netdevice name (without 'ap' postfix, i.e., wlan0 uses wlan0ap for
# management frames); ath0 for madwifi
interface=wlx1cbfce699b7f

##### IEEE 802.11 related configuration #######################################
# SSID to be used in IEEE 802.11 management frames
ssid2="nqm-britannic-brski-open"

# Enable IEEE 802.11n 2.4 GHz
hw_mode=g
ieee80211n=1
# Ralink RT5370 supports 40 MHz bandwidth, see datasheet
ht_capab=[SHORT-GI-40][HT40+][HT40-]

channel=6

Then, you can start/restart hostapd with:

systemctl restart hostapd@wlx1cbfce651dc4.service hostapd@wlx1cbfce699b7f.service

You can enable hostapd, so that it starts automatically on boot, by using:

systemctl enable hostapd@wlx1cbfce651dc4.service hostapd@wlx1cbfce699b7f.service

Configuring dnsmasq​

Make two new SYSV init files called /etc/default/dnsmasq.%i (replacing %i with your instance name).

E.g. /etc/default/dnsmasq.wlx1cbfce699b7f:

DNSMASQ_EXCEPT="lo"
DNSMASQ_INTERFACE='wlx1cbfce699b7f'
DNSMASQ_OPTS='--bind-interfaces --dhcp-range=192.168.16.100,192.168.16.199,4h'

E.g. /etc/default/dnsmasq.wlx1cbfce651dc4:

DNSMASQ_EXCEPT="lo"
DNSMASQ_INTERFACE='wlx1cbfce651dc4'
DNSMASQ_OPTS='--bind-interfaces --dhcp-range=192.168.17.100,192.168.17.199,4h'

Then, you can start/restart the dnsmasq services by doing:

systemctl restart dnsmasq@wlx1cbfce651dc4.service dnsmasq@wlx1cbfce699b7f.service
Configuring dnsmasq to only start after hostapd​

Unfortunately, since hostapd temporarily disables the wifi interface on startup, we cannot start dnsmasq at the same time as hostpad, we need to start it a few seconds afterwards.

To do this automatically, we can create a systemd unit override to make dnsmasq only start after hostapd starts up.

This can easily be done by using the sudo systemctl edit dnsmasq@.service command, and entering in the following:

[Unit]
# We can only start dnsmasq after hostapd starts, because starting them both
# at the same time fails
BindsTo=hostapd%i.service
After=hostapd%i.service

[Service]
ExecStartPre=/bin/sleep 5

(or manually creating a /etc/systemd/system/dnsmasq@.service.d/override.conf)

After we make this override, we can do a systemctl daemon-reload, then enable dnsmasq to start on boot (make sure you enable hostapd@ too!):

systemctl enable dnsmasq@wlx1cbfce651dc4.service dnsmasq@wlx1cbfce699b7f.service