# Network The physical layout of the network is as follows: :::{mermaid} flowchart LR internet["Internet"] upstairs_wifi["Upstairs WiFi AP"] downstairs_wifi["Downstairs WiFi AP"] front_camera["Front Camera"] porch_camera["Porch Camera"] wg_clients["Wireguard Clients"] subgraph marks_office ["Mark's Office"] subgraph subgraph_padding_marks_office [ ] modem["Fibre ONT"] router["Core Router"] main_switch["Main Switch"] poe_switch_upstairs["PoE Switch"] rpi01/02 desktop01 end end subgraph garage ["Garage"] subgraph subgraph_padding_garage [ ] poe_switch_downstairs["PoE Switch"] lab_switch["Lab Switch"] lab01..06 nfs01 srv01 end end subgraph hallway ["Hallway"] subgraph subgraph_padding_hallway [ ] upstairs_wifi downstairs_wifi end end subgraph outside ["Outside"] subgraph subgraph_padding_outside [ ] porch_camera front_camera end end internet --> modem modem --> router router --> main_switch main_switch --> rpi01/02 main_switch --> desktop01 main_switch --> poe_switch_upstairs main_switch --> poe_switch_downstairs main_switch --> lab_switch poe_switch_upstairs --> upstairs_wifi poe_switch_upstairs --> downstairs_wifi poe_switch_upstairs --> porch_camera lab_switch --> lab01..06 lab_switch --> nfs01 lab_switch --> srv01 poe_switch_downstairs --> front_camera srv01 -.-> wg_clients %% empty subgraphs are wrapped around some components to create more padding classDef subgraph_padding fill: none, stroke: none class subgraph_padding_marks_office subgraph_padding class subgraph_padding_garage subgraph_padding class subgraph_padding_hallway subgraph_padding class subgraph_padding_outside subgraph_padding classDef outer_group fill: none class marks_office outer_group class garage outer_group class hallway outer_group class outside outer_group ::: Elements of this layout are explained in more detail below, along with details of IP assignment and other tools in use. ## Core Router The core router is currently a MikroTik hEX S device. It can be accessed at [http://10.0.0.1](http://10.0.0.01) when inside the LAN. In the future it may be replaced with a DIY build. ### Internet Connection The fibre ONT (optical network terminal) translates light signals from the outside network to copper ethernet for the network inside the house. The first device after the ONT is the router, which provides the actual connection to the Internet via PPP (Point-to-Point Protocol). PPP is how the router authenticates with our ISP (PlusNet at the time of writing) to access the network. ### Router-Level Firewall The MikroTik router provides the main firewall for the network. It is configured under IP > Firewall on the router and is kept simple: - Outgoing traffic is allowed. - LAN-to-LAN traffic is allowed. - Incoming traffic is mostly disallowed: - NAT (network address translation) is used to route incoming SSH, HTTP and HTTPS traffic to the relevant services. - All other incoming traffic is dropped. ## Site Networking The two Raspberry Pis provide "site network" services (i.e. network services consumed by the whole house, as compared to "host network" services that run on a single machine). All site-network services are managed via [Ansible][ansible]. ### DHCP [Kea][kea] is a [DHCP][dhcp] (Dynamic Host Configuration Protocol) server that runs in an primary/secondary pair across the servers. It is the service that hands out IP addresses to clients when they join the network, along with other information like the network gateway IP, DNS servers, and the network's domain name (which is `lan.tatsu.casa`). DHCP reservations are used to _reserve_ a particular IP address and make sure it is always given to the same client when it connects (based on the client's MAC address). This is how all hosts have their network details configured, making the DHCP server on the router the source of truth for who gets which IP. When a client that does not have a corresonding reservation, it is given an address from a pool of unreserved addresses (see below). ### DNS Resolution and Filtering [BIND9][bind] is a recursive[^recursive_resolver] DNS resolver that runs on both RPi servers. As well as recursively resolving requests for external domains, it also contains static entries for `*.lan.tatsu.casa` domains. BIND9 isn't designed as DNS filtering service (like Pi-Hole or Blocky), but it still provides that service for us. BIND9 is configured with a "Response Policy Zone" (RPZ) that blocks resolution of most advertising, tracking and malware domains using a domain list from [this repo](https://github.com/hagezi/dns-blocklists). [^recursive_resolver]: Being a recursive resolver roughly means that when resolving a domain like `woodhouse.tatsu.casa`, Unbound will first reach out to the authoritative name servers for `.casa` to find out who owns `tatsu.casa`, then repeat until the whole domain has been resolved. ## Wireguard [Wireguard][wireguard] (WG) is a lightweight VPN that is used to create secure tunnels between hosts on the Tatsu network and hosts that are not actually present on the LAN - like mobile phones and laptops. It allows us to treat non-local hosts as if they were on the home network. WG creates a new network interfaces on each host, which is why all hosts using WG have a separate WG IP address as well as their "normal" one. It uses pre-arranged public/private keys that are shared between hosts to secure communication between them. WG configuration is managed via [Ansible][ansible]. ## WiFi and OpenWRT There are two WiFi access points (APs): one on the upstairs landing and one in the downstairs hallway. They are both TP-Link EAP225 v3 units and are powered directly from the network switch using power-over-ethernet (PoE). The APs have been flashed with [OpenWRT][openwrt] firmware, replacing the original TP-Link firmware that they came with. This was done for several reasons, but mainly because OpenWRT is ultimately just Linux, which allows the APs to be connected to via SSH, managed using [Ansible][ansible] (instead of TP-Link's problematic Omada tooling), etc. A note on WiFi security: TP-Link only supports up to WPA2 but OpenWRT has support for WPA3. The APs still in run WPA2 mode because not all devices support WPA3 yet, like the [ESP](../smart-home/devices.md#esphome) boards. We could run WPA2/WPA3 split mode, but the hallway tablet only supports that if management frame protection is also enabled, which the ESPs don't support. ## Host Networking Networking configuration for all hosts is managed via [Ansible][ansible] including things like the host firewalls, DNS servers and any floating IP addresses. ### Host-Level Firewalls Firewalls are implemented on all hosts using [nftables][nftables] (NF = net filter), which is a modern replacement for iptables. These firewalls are configured via [Ansible][ansible] and generally block all incoming traffic except for that which is expected and allowed. ## Web Proxy Incoming web traffic (HTTP and HTTPS) from the outside world is directed to Envoy by the router. ### Envoy & Envoy Gateway [Envoy][envoy] is a service running in the [Kubernetes cluster](./lab-architecture) that handles [TLS termination](tls_termination) and routes requests to the correct service (usually based on domain name). It is also responsible for integrating with Authelia (see below) to authenticate requests. [Envoy Gateway][envoy_gateway] is a Kubernetes-native wrapper around Envoy that serves as a control plane for it. Envoy's own config is quite complex and won't do things like discovering other services in Kubernetes, so we configure Envoy _Gateway_ with fairly simple primitives, then it configures Envoy for us. ### Authelia [Authelia][authelia] is another service running in the [Kubernetes cluster](./lab-architecture) that provides authentication for every request. Users are currently configured manually in config and require MFA. Authelia allows complex access control rules to be configured, which are used to allow some services to be public (such as our personal sites) or to require only single-factor login for some services (such as for the Woodhouse dashboard, accessed by a service account). ## Annex: IP Schema :::{note} For the in-use configuration of IP addressing, see the DNS and DHCP config files in [Ansible][ansible]. ::: The Tatsu LAN is `10.0.0.0/16`, i.e. ~65k addresses in the form `10.0.x.y`. This large address space is split up into smaller subnets, listed below alongside other ranges used beyond the LAN. This is division allows us to apply some structure and control traffic between types of devices. | **Subnet** | **Range Size** | **Use** | |-------------------|----------------|---------------------------------------------------| | `10.0.0.0 / 23` | \~500 | Network infrastructure | | `10.0.2.0 / 23` | \~500 | Reserved for exposed and floating IPs - see below | | `10.0.4.0 / 23` | \~500 | Physical hosts | | `10.0.6.0 / 23` | \~500 | *Unused* | `10.0.8.0 / 22` | \~1k | IoT | | `10.0.12.0 / 22` | \~1k | DHCP for unknown hosts | | `10.0.16.0 / 20` | \~4k | *Unused* | | `10.0.32.0 / 19` | \~8k | *Unused* | | `10.0.64.0 / 18` | \~16k | *Unused* | | `10.0.128.0 / 17` | \~32k | *Unused* | | `10.1.0.0 / 24` | \~250 | Wireguard | ### `10.0.0.0 / 23` - Network Infrastructure - `10.0.0.1` - Core router - `10.0.0.10` - RPi 1 (`ns01.lan.tatsu.casa`) - `10.0.0.11` - RPi 2 (`ns02.lan.tatsu.casa`) - `10.0.0.20` - Upstairs WiFi AP - `10.0.0.21` - Downstairs WiFi AP ### `10.0.2.0 / 23` - Exposed and Floating IPs :::{note} Other than the external entrypoints, if these IPs have a domain it must sit under `.lan.tatsu.casa`, indicating that they cannot be accessed when outside the LAN. ::: - `10.0.2.5` - Gitea SSH (`gitea.lan.tatsu.casa`) - `10.0.2.6` - Mosquitto MQTT (`mqtt.lan.tatsu.casa`) - `10.0.2.10` - PXE boot server - `10.0.2.11` - qBittorrent port-forward - `10.0.2.12` - `cluster01` control plane (`cluster01.lan.tatsu.casa`) - `10.0.2.13` - External entrypoint (see [web proxy](#web-proxy)) ### `10.0.4.0 / 23` - Physical Hosts - `10.0.4.1` - `desktop01` - Mark's desktop - `10.0.4.2` - `laptop01` - Mark's laptop - `10.0.4.5` - `srv01` - `10.0.4.6` - `nfs01` - `10.0.4.8` - `laptop02` - Ana's laptop - `10.0.4.9` - `lab01` - `10.0.4.10` - `lab02` - `10.0.4.11` - `lab03` - `10.0.4.12` - `lab04` - `10.0.4.13` - `lab05` - `10.0.4.14` - `lab06` ### `10.0.8.0 / 22` - IoT - `10.0.8.1` - Spare bedroom room Chromecast - `10.0.8.2` - Kitchen Google Home - `10.0.8.3` - Living room Google Home Mini - `10.0.8.4` - Boiler switch (ESP01 + [](../smart-home/devices.md#esphome)) - `10.0.8.5` - Garage dehumidifier (ESP01 + [](../smart-home/devices.md#esphome)) - `10.0.8.6` - Hallway dashboard tablet - `10.0.8.7` - Xmas tree lights (ESP32-based 3rd-party board + [](../smart-home/devices.md#wled)) - `10.0.8.8` - Downstairs robot vacuum cleaner (Dreame L10s Ultra + [Valetudo][valetudo]) - `10.0.8.11` - Driveway alarm box (ESP01 + [](../smart-home/devices.md#esphome)) - `10.0.8.12` - Car tracker (ESP12F + [](../smart-home/devices.md#esphome)) - `10.0.8.14` - Living room TV - `10.0.8.15` - Driveway CCTV camera - `10.0.8.16` - Porch CCTV camera - `10.0.8.17` - Roaming CCTV camera 1 - `10.0.8.18` - Roaming CCTV camera 2 ### `10.0.12.0 / 22` - DHCP - DHCP range for devices without static IPs or DHCP reservations ### `10.1.0.0 / 24` - Wireguard - `10.1.0.1` - `srv01` (Wireguard "hub") - `10.1.0.2` - `laptop01` - Mark's laptop - `10.1.0.3` - Mark's phone - `10.1.0.4` - Ana's phone [ansible]: https://gitea.tatsu.casa/tatsu-deploy/ansible [authelia]: https://www.authelia.com [bind]: https://www.isc.org/bind [dhcp]: https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol [kea]: https://www.isc.org/kea [nftables]: https://wiki.nftables.org/wiki-nftables/index.php/Main_Page [openwrt]: https://openwrt.org [systemd]: https://en.wikipedia.org/wiki/Systemd [tls_termination]: https://en.wikipedia.org/wiki/TLS_termination_proxy [valetudo]: https://valetudo.cloud [envoy]: https://www.envoyproxy.io [envoy_gateway]: https://gateway.envoyproxy.io [wireguard]: https://www.wireguard.com