Best practices for setting up an info-beamer device


Hardware tips and tricks

To build a reliable device here are a few suggestions. Most of them are learnt from experience.

Use a proper power adapter

If you use a cheap power adapter your SD card might get corrupted randomly. Use at least a 1500mA power adapter. If you intend to use use Wi-Fi (see below) you should get a 2000mA adapter to be safe.

A strong indicator that something is wrong is a small lightning symbol in the top right corner of the screen. This indicates that your power supply is too weak. Do not ignore this warning! This is the number one source for all kinds of problems like SD cards getting corrupted! Just get a better power adapter.

Do not use TV USB ports as power source

Most of them don't generate enough power for the Pi. As a result your Pi might not work reliably or your SD card might get corrupted. It's always a better idea to use a power adapter.

Use a high quality SD card

Please purchase a high quality SD card for your device. In the worst case cheap SD card might even be fakes that report the wrong capacity leading to certain file system corruption. Consider purchasing a card from a reputable brand like SanDisk, Samsung or Kingston.

Your SD card should provide the capacity needed to store all assets that you need for your visualization. The more capacity the better as the info-beamer operating system caches assets so they are only downloaded once. A good size is probably 8 or 16GB.

Using SD cards larger than 32GB is not recommended. Please also ready the next recommendation regarding SD card size.

When formatting your SD card: Don't use exFAT

For SD cards larger than 32GB, exFAT is often the default filesystem when formatting the SD card. The problem is that the Raspberry Pi doesn't understand exFAT and cannot boot from that filesystem. It can only boot from FAT32 formatted filesystems. So make sure you format large SD cards with the FAT32 filesystem. Learn more about this on the official Raspberry Pi page.

Don't use Wi-Fi if possible

If your installation allows this, consider using an ethernet cable connection to your device instead of using Wi-Fi. While Wi-Fi works, it's prone to more problems. You get the best reliability by using ethernet.

Set a fixed screen resolution

An info-beamer hosted device tries to automatically detect the resolution of the attached screen. This will work if the screen can be queried while the device starts. If you turn on or attach a screen later the device might select a wrong resolution.

If you know the resolution of your screen and are sure that it's not going to change, you should set a fixed output resolution. That way the resolution will always be set to the one you configured regardless of that an attached screen is doing.

If you're not using info-beamer hosted you might call tvservice manually to set the resolution to a known good value.

Use a good case

info-beamer uses the GPU of your Raspberry Pi. So be sure to have a case that allows air flow. Otherwise your device might get too hot and become unreliable.

Setting up hosted

info-beamer hosted makes it easy to setup devices and provides a configuration interface to control them remotely. If you don't want to deal with a complex manual installation process, using info-beamer hosted is the easiest way to get started.

Required network access

Following the principle of least privilege it might make sense to isolate info-beamer hosted devices in your network from other devices. Right now info-beamer devices require access to the following network resources:

Protocol Hostname / description Port Reason
TCP info-beamer.com [1] 443 Websocket connection for controlling the device
TCP sync.info-beamer.com [2] 80 & 443 [3] Downloading content/system updates
TCP ping.infobeamer.com [4] 80 Detecting network connectivity, captive portals and fallback system time
TCP Local network 11111 Optional feature: peer-to-peer download acceleration
UDP Configured DNS server [5] 53 Resolving hostnames
UDP Configured NTP servers [6] 123 Getting system time
UDP Local DHCP server 67 Getting IP configured
UDP Local broadcast domain [7] 11111 Optional feature: UDP peer discovery
  1. Currently on DigitalOcean AMS
  2. Uses Amazon Cloudfront. Here is a blog post with their IP ranges.
  3. Port 80 is used only for system updates. An update only contains public data as it's the same install.zip file you can download on the devices page. It is of course cryptographically signed to prevent tempering. HTTP is used as the device might not be able to provide a correct time which would make verifying certificates tricky.
  4. Behind CloudFlare. Have a look at https://www.cloudflare.com/ips/ for potential IP addresses.
  5. Defaults to 8.8.8.8, but can be changed.
  6. Defaults to {0,1,2,3}.debian.pool.ntp.org, but can be changed.
  7. Requests are broadcasted to 255.255.255.255.

The hosted devices only support IPv4 at the moment. IPv6 support might be added in the future.

Security considerations

info-beamer hosted was designed with security in mind. These sections will help you understand how info-beamer tries to minimize the risk of running a device and what it can and can't protect against.

Exposed network services

By default a running device exposes no external ports and will only respond to ICMP requests like a ping request (see also service scripts). If you decide to turn on SSH access it will start an SSH server on port 22 that will allow login as root using keys-only authentication. info-beamer hosted helps you to avoid the usual TOFU problem as you can easily see the SSH fingerprint for each of your devices on its detail page. SSH should only be used for debugging purposes and must never be used to modify content on a device automatically.

If you decide to open up info-beamer's ports the device will additionally open up TCP and UDP on port 4444 and will allow input from external sources. Depending on the running code this might cause problems. Unless your running visualization needs input from external sources and you're running your installation in a trusted network there is no reason to do this.

Additionally info-beamer hosted os includes peer-to-peer support which, among other things, accelerates downloads if multiple devices share the same uplink and can reach each other. By default this feature is deactivated. See the documentation to learn how to enable this service.

Network communication

When booting the device might use WiFi if configured. The credentials are stored in a plain text file on the device itself. Since the device has to access the credentials automatically it would not make any difference if that file would be encrypted. The decryption algorithm and its key would have to be stored on the device too which would defeat the purpose of encryption. See also physical security.

Once a network is set up the device will by default request an IP address using DHCP unless configured to use a static IP address. DHCP is unencrypted and unsigned, so make sure there is no rogue DHCP server in your network.

The device uses the Google Public DNS servers by default unless configured manually. DNS (as used by the hosted device) is unencrypted and unsigned unless you activate the DoH (DNS over HTTPS) feature.

The device tries to get a correct system time using NTP. By default the DHCP provided NTP server (DHCP option 42) is used. If none is provided or a static network configuration is used, the Debian NTP pool at {0,1,2,3}.debian.pool.ntp.org is used instead. NTP is unencrypted and unsigned but responses from different servers are compared to increase the chances of getting the correct time. You can also configure a local NTP Server. Failure to get a proper system time using NTP within the first few minutes will trigger a fallback solution: The device will contact http://ping.infobeamer.com/ping and use the supplied Date header in the response. The time might not be exact but it's probably better than having no proper time at all.

Every few minutes the device tries to verify network connectivity by issuing a HEAD request to http://ping.infobeamer.com/ping. If it receives no response or an invalid response a couple of times, the device will completely restart the network in an attempt to reestablish connectivity.

Once the device is running, all communication by the syncing process on the device is done using TLS exclusivly. It will connect to info-beamer.com and set up a permanent websocket connection that is used to trigger content updates on the device. It will also be used to query telemetry data, issue debug commands and the live preview screen on the device details screen.

Content updates (either triggered using the websocket connection or detected by polling) are handled by first requesting the intended state on the device from the content servers. All content files not yet available on the device are then downloaded from the content server. All communication is secured by TLS. Alternatively locally detected info-beamer devices can be used to fetch locally available content faster. See the peer-to-peer section for more information.

You can instruct a device to send its logs to a remote syslog service. The log content is sent unencrypted. If you can, you should avoid sending logs as they contain sensitive information (like the device syncing key or urls to device content).

While a device is running it will try to reach out to the update server once per day to see if a new OS version is available. While the communication itself isn't protected by TLS all files downloaded are signed, so the device can verify that it is indeed an official info-beamer update. TLS isn't used as the files are publicly available - it's the exact file you get when you download the hosted OS installation zip file from here - and to enable updates even if a correct system time isn't available at that point. If there's a critical system update available, all devices can be forced to reboot but will usually honor the specified maintenance window configured on the details page for each device.

An attacker that gains control of the network a device is using won't be able to change the running visualization simply by intercepting or modifying network traffic unless the running visualization itself requests data from unsecured (e.g. HTTP) external sources. What's running on the device is completely signed by the info-beamer hosted service and all content running on the device is transferred to the device using TLS. The code and data on the device is exactly what is configured in the web configuration interface. An attacker might of course prevent the device from getting any updates by simply blocking it from opening new network connections. But there is nothing the device (or any other device) can do against that.

Running visualizations

Everything displayed on the screen is controlled by the running visualization. Visualizations are written in a full programming language. info-beamer sandboxes this code and prevents it from accessing the network.

Running visualizations can also be accompanied by a service script which can potentially interact with the outside world to (for example) fetch information from a web server or provide their own network service. Service scripts could be written in any language. At the moment, the hosted runtime environment only provides Python and shell script out of the box, but using a statically linked ARM binaries is possible as well.

Each service script runs as a unique user id. Service scripts can't accidentally overwrite package files, assets or otherwise change the running visualization but they can (by design) access the local info-beamer process using TCP or UDP to interact with it.

Service scripts can also bind to all network interfaces which allows them to be reachable from the outside world. This can be used to (for example) start a local FTP server so other legacy services can upload dynamic content to a device.

A local firewall rule prevents any service script from accessing remote network resources or exposing a network service by default. Packages can declare the need for network access in their node.json metadata file. You can see the required package permissions on the package details page once you enable developer options.

Unless you vet every package yourself, you should only run packages on your device if you trust them or their developer. Once you have imported a package into your account it won't be updated automatically unless you explicitly click the Check for updates button on its details page or you push a new version using git.

Peer-to-peer

info-beamer hosted os can optionally enable certain peer-to-peer (P2P) services that accelerate downloads and help to keep the clock synchronized on your devices. Once enabled, your devices start additional services that listen on port 11111 on both UDP and TCP.

UDP peer discovery

The UDP port 11111 is opened by the syncer process. It listens for incoming UDP broadcast packets and sends back a response. Devices only respond to other devices that run a compatible info-beamer hosted os version. The broadcast request (sent to 255.255.255.255) contains a protocol version, a nonce and the local device time. The response relays that time back and adds the local device time of the receiver. The included nonce prevents blind responses from sources outside of the broadcast domain.

This allows the sender to calculate the network latency between both devices and an estimated remote device time. This time can then be compared to the local time and used to decide if the NTP client should be restarted in order to get a better local device time. Restarts happen at most every 5 minutes to limit NTP traffic to a sensible maximum.

The communication itself happens in clear text and a malicious actor can intercept and impersonate an info-beamer hosted device. Doing so doesn't put your installation in danger. The worst that can happen is that your devices restart NTP every 5 minutes. While unnecessary, it doesn't have any negative effect on your devices.

The UDP service is implemented in Python and there is little risk of accidental vulnerabilities that might happen in less safe languages. There is no rate limit at the moment. The amplification factor (average response size / average request size) is approximately 1.25 and poses little risk for abuse.

Download acceleration

The TCP port 11111 is opened by an additional peer-to-peer (P2P) daemon process implemented in python. It's a low priority python based web service running as its own user in a sandbox with minimal readonly access to the filesystem.

The syncer daemon usually downloads content from the hosted CDN (sync.info-beamer.com) using HTTPS. If P2P is enabled, every content download is first tried locally. Instead of reaching out to the CDN, the syncer instead contacts the local P2P daemon. The syncer provides the expected content file size, the content hash sum as well as a list of local device IPs discovered by the UDP peer discovery.

The P2P daemon then reaches out to all provided IP addresses to see if the peer offers the requested file. These info requests happen in parallel with a strict timeout of 0.5 seconds. The query and response also include a challenge/response system that allows the requesting party to verify that the responder can actually provide the file requested. The response includes information about the number of currently active downloads on the responding device.

info-beamer hosted organizes all package files and assets for delivery in a unique and simple way: Every piece of content is identified by its md5 hash sum (content_md5). Knowing the content_md5 of a file or having access to the file itself (from which the content_md5 can be calculated) allows a device to download that file from the hosted CDN. During P2P communication the content_md5 is never revealed, so a malicious actor with access to this communication can't use intercepted data to learn the content_md5 and therefore can't download the content from the hosted CDN. Instead the public_id is used in all exchanges. It is calculated as follows:

content_md5 = md5(content)
content_key = hmac(content_md5, "content_key")
public_id = hmac(content_key, "public" | content_md5)

Since hmac is a one way function, there's no way to calculate the content_md5 simply by having access to the public_id. The only way to create a mapping public_idcontent_md5 is to have access to the content_md5. The challenge/response system mentioned above uses a similar setup:

challenge = nonce
response = hmac(content_md5, "challenge" | challenge)

Since it's impossible to calculate a correct response without having access to the content_md5 value, the responder can proof that it has access to this value and therefore the content requested.

Once the requesting party knows which peers can provide the file, it selects one with the least number of active downloads. This provides a balanced distribution of downloads among peers if there are many devices in the local network.

The download request itself specifies the public_id of the requested file as well as the requested range within the file. The response is a chunked stream of encrypted blocks of 64k bytes each. Each block is AES encrypted using the content_key (see above) using CBC with a random IV for each block. A malicious actor can observe or request a download, but can't decrypt the content as that would require access to the content_key which can't be derived from the public_id. Similarly to the info requests above, the transfer request also includes a challenge/response system that enables the receiving party to quickly reject downloads from a malicious actor.

The received content is decrypted on the receiving device and like with CDN downloads is hashed to make sure the data received acutally matches the expected value of content_md5. If there is any problem while trying to download the file from the P2P system, the syncer falls back to downloading from the CDN. A malicious actor might therefore delay downloads briefly but can't prevent them as devices simply switch to the CDN instead. P2P downloads are completely optional.

Note that P2P downloads are not restricted to devices owned by the same account. Any device in the local network that can provide the requested content can be used for P2P downloads. This doesn't leak any sensitive information that isn't already known to both parties. The only information gained is that the requesting devices uses the same content. Neither party can learn about content to which only one of the parties has access.

Physical Security

A Raspberry Pi cannot be secured against exposing data on the SD card if the device (and its SD card) is physically stolen as there is no way of setting up disk encryption without also exposing the key used for encryption. Furthermore a Raspberry Pi device doesn't contain enough persistent entropy (like serial numbers/hardware identifiers) to generate a unique device key.

A stolen SD card contains all information required to access the configured network. For that reason it makes sense to treat a device as untrusted, which is a good idea anyway. If you can, you should firewall the device from your internal network to minimize the impact of a stolen device.

All downloaded content is cached on the device SD card. Content includes both images and videos as well as code and configuration for the running visualization. Old content isn't removed unless the device is running out of disk space. This enables a device to switch between content without redownloading it every time. Right now it's not possible to manually purge the content of the device cache remotely.

When you delete a device using the web interface all files will be deleted from the filesystem but won't be overwritten at the moment. So it is still possible to access the files using data recovery tools. SD cards usually also use Wear leveling so even overwriting files wouldn't guarantee that data can't be recovered.

Access to the SD card also allows access to the syncing key that's used by the device to detect new updates. This key allows an attacker to learn about the current and future device content. The only way to prevent an attacker from basically mirroring the device content is to delete the old device from your account and to setup a completely new SD card (since it might be possible to retrieve the syncing key on a previously used card using data recovery tools) and adding the new device to your account again.

While an attacker might learn about the content on a device, it's not possible to access an info-beamer.com account simply by stealing one of its devices as there is nothing on the device that would allow access to the configuration interface.

You might use superglue to physically make it more difficult to remove the SD card from a device. A Raspberry Pi running hosted won't respond to keyboard input by default so it's more difficult for an attacker to access the device data. Of course that prevents you from switching SD cards should there be a hardware problem. The best course of action is probably to secure a device against theft.

Summary

The info-beamer hosted device was designed with security in mind but can't protect against certain threats. Being as transparent as possible allows you to assess those risks and make informed decisions that wouldn't be possible if info-beamer.com just promised to take security seriously without going into details. If you have any questions or suggestions, don't hesistate to get in contact.

Setting up info-beamer

info-beamer hosted will solve all of the following problems for you, so you don't have to. Learn more about how it creates a highly reliable system. Of course you can always create your own SD card and setup your own software instead. These hints and a related blog post might help you.

Minimize SD card writes

If you intend to use a normal Raspberry Pi distribution like Raspbian it makes sense to configure the system in a way that minimize writes to the SD card. You can try to mount the root filesystem read-only or use filesystem such as tmpfs to hold log files.

Reliably start info-beamer

You most likely want to automatically start info-beamer every time your Pi starts. Have a look at this blog post about running info-beamer in production.

Don't load images/videos from network file systems

If you have multiple displays, you might be tempted to have a single network share that your Pis mount over the network. Running info-beamer from a networked filesystem is a bad idea:

  • You introduce a single point of failure: If the file server goes down, all displays will go down. rsyncing locally solves that.
  • Inotify (the ability to get notified of files changes by the kernel) isn't really usable with networked file systems.
  • The unix file system semantics feature from the blog post most likely won't work.

In short: Don't use Windows shares or other networked file systems. Instead always keep assets (images/videos) locally on the Pi. The easiest way is to have rsync running from a crontab to keep files on the Pi in sync with a server.