Skip to content

WIP-0001: Whitebox Network Configuration Specification

Introduction

This document proposes a standardized network configuration for whitebox development and production environments. The goal is to establish a consistent and predictable network configuration for all running services so that it is easily discoverable regardless of the environment.

Network Topology

Network Topology

The network is split into two parts:

  1. Host Network: This is the network that the client devices would connect to. We will only configure this when we are setting up a dedicated machine for whitebox. While configuring the network, subnet will be set to 10.38.0.0/24 and the DNS server will be set to 10.38.128.2, which will be running on the same machine under the docker network with the subnet being 10.38.128.0/17. More on this later.

When running Whitebox on your local development machine, only the client device IPs will differ from this schema. The internal Docker network structure - including the DNS server (10.38.128.2) and web-proxy (10.38.128.3) - will maintain the same IP addresses as defined in this document regardless of your local network configuration. This ensures consistency across all development environments. The only difference will be that your local machine would be updated to point to the DNS server running on the docker network.

  1. Docker Network: This is the network that all the services will run on. It will have it's own subnet (10.38.128.0/17) and DNS server. Each service will be assigned a static IP address within this subnet.

To ensure IP addresses are assigned in a predictable manner, we will reserve a range of IP addresses for each type of service. Example:

Service Type IP Range
Router 10.38.128.0/24
DB Apps 10.38.129.0/24
Core Apps 10.38.130.0/24
Other Apps 10.38.131.0/24

Besides these IP ranges, other devices like remote cameras might have their own separate IPs and network configurations.

Above, the /24 subnet is for representation purposes only. They are represented as /24 to show that the first 3 octets are fixed and the last octet is variable based on the service type. Other apps may go beyond the /24 range if needed to accommodate more services.

To remember the IP subnet 10.38, you can think of 38 being the WhiteBox acronym WB, where 3 represents W rotated 90 degrees and 8 represents B.

When configuring a dedicated machine, we will also add a routing rule to the host's routing table to ensure traffic flows between the host and containers.

sudo ip route add 10.38.128.0/17 dev docker0
sudo ip route default via 10.38.128.2

Note: 10.38.128.1 is assumed to be the default gateway for the docker network. Hence, it was reserved and could not be used for any services as docker will complain that the IP is already in use. DNS service was moved to 10.38.128.2 to avoid this issue. Investigate if 10.38.128.1 could somehow be used for the DNS server.

Docker Network Configuration

The docker network will be configured as follows:

networks:
  whitebox-net:
    name: whitebox-net
    driver: bridge
    ipam:
      config:
        - subnet: 10.38.128.0/17

services:
  backend:
    networks:
      whitebox-net:
        ipv4_address: 10.38.130.1
    dns:
      - 10.38.128.2
    # ...
  # ...

Domain Name Scheme

  • Domain: whitebox.local
  • Service Subdomains:
  • Backend: backend.whitebox.local
  • Frontend: frontend.whitebox.local

DNS Server

For DNS & IP allocation, we use dnsmasq, which has good ARM support:

dnsmasq.Dockerfile

FROM whitebox-base:latest

COPY packaging/dnsmasq/dnsmasq.conf /etc/dnsmasq.conf
COPY packaging/dnsmasq/dnsmasq.hosts /etc/dnsmasq.hosts

compose.yml

services:
  dnsmasq:
    build:
      context: .
      dockerfile: packaging/docker/dnsmasq.Dockerfile
    container_name: dnsmasq
    restart: unless-stopped
    networks:
      whitebox-dev-net:
        ipv4_address: 10.38.128.2
    cap_add:
      - NET_ADMIN

dnsmasq.conf

# Listen on all interfaces
interface=*

# Don't use /etc/resolv.conf
no-resolv

# Set default domain
domain=whitebox.local

# Forward non-local queries to Quad9 DNS servers
server=9.9.9.9
server=9.9.9.10

# Don't forward reverse lookups for private IPs
bogus-priv

# Don't forward queries for plain names
domain-needed

# Add hosts from the hosts file
addn-hosts=/etc/dnsmasq.hosts

# Cache settings
cache-size=1000
local-ttl=3600

# Listen on all available addresses
listen-address=0.0.0.0

# Log to stdout for debugging
log-queries
log-facility=/var/log/dnsmasq.log

# CNAME Records
cname=whitebox.local,web-proxy.whitebox.local
cname=api.whitebox.local,web-proxy.whitebox.local

dnsmasq.hosts

10.38.128.2 router.whitebox.local
10.38.128.3 web-proxy.whitebox.local
; ... other services to expose via the web proxy

10.38.130.1 backend.whitebox.local
10.38.130.2 frontend.whitebox.local
; ... each service will have its own entry for internal usage within the docker network

Routing

The DNS server (dnsmasq) will resolve domain names like whitebox.local and api.whitebox.local to the web proxy's IP address (10.38.128.3). When client devices make requests to these domains, they'll be directed to the web proxy (nginx).

The nginx web proxy will then act as a reverse proxy, forwarding these requests to the appropriate internal services based on the domain name used. For example:

  • Requests to whitebox.local will be forwarded to the frontend app running at 10.38.130.2:80
  • Requests to api.whitebox.local will be forwarded to the API service running at 10.38.130.1:80

Note: Services like frontend and backend will be exposed on port 80 within the container and will only be accessible via the web proxy as a standard practice.

nginx.Dockerfile

FROM whitebox-base:latest

COPY packaging/nginx/nginx.conf /etc/nginx/nginx.conf
COPY packaging/nginx/conf.d /etc/nginx/conf.d

compose.yml

services:
  nginx:
    build:
      context: .
      dockerfile: packaging/docker/nginx.Dockerfile
    container_name: nginx-proxy
    restart: unless-stopped
    networks:
      whitebox-dev-net:
        ipv4_address: 10.38.128.3
    depends_on:
      - dnsmasq

default.conf

# Default server that will just close the connection for unmatched hosts
server {
    listen 80 default_server;
    server_name _;
    return 444;
}

# api.whitebox.local
server {
    listen 80;
    server_name api.whitebox.local api;

    location / {
        proxy_pass http://10.38.130.1:80;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

# whitebox.local
server {
    listen 80;
    server_name whitebox.local;

    location / {
        proxy_pass http://10.38.130.2:80;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

# ...

Additionally, each whitebox unit will have its own unique subdomain, e.g. john.whitebox.aero, which will be resolved to different locations based on the context:

  • Locally: john.whitebox.aero will resolve to 10.38.128.3 (web-proxy.whitebox.local) and proxy requests to the frontend app.
  • Remotely: john.whitebox.aero will resolve to the web server hosted on the internet, which would proxy to the frontend app running on the whitebox unit when connected to the internet. Or maybe to cached backup version in the cloud when the whitebox unit is offline.