Skip to content

Reach the cloud from your LAN

Two settings on the LAN make the cloud usable from it:

  1. A static route for each floating IP range, with the node as the next hop. The node routes the range itself; the router only sends it there.
  2. DNS forwarding of the parent domain (for example cloud.internal) to the node, port 53.

Set both once on the router and the LAN’s DNS server, and every machine has them. The examples use the node 192.0.2.10, the LAN 192.0.2.0/24, the floating IPs 198.51.100.0/24 and the parent domain cloud.internal.

stratum-installer client-setup prints the same for the node it installed, with commands for one machine.

Any router: add a static route, destination 198.51.100.0/24, next hop 192.0.2.10. Then:

  • Machines on other VLANs or zones need a firewall rule allowing them to the range.
  • Machines on the node’s own network send through the router, but the node answers them directly. A router that tracks connections sees only half of each one and may drop the rest: allow, or exempt from state checks, the traffic between that network and the range.
Router Route DNS forward
UniFi Settings › Routing › Static Routes: type Next Hop, network 198.51.100.0/24, next hop 192.0.2.10. Settings › Policy Engine, a DNS policy of type Forward Domain, cloud.internal to 192.0.2.10.
pfSense System › Routing: a gateway 192.0.2.10 on the LAN, then a static route to it. Enable “Bypass firewall rules for traffic on the same interface”. Services › DNS Resolver › Domain Overrides.
OPNsense System › Gateways, then System › Routes. Enable “Static route filtering” under Firewall › Settings › Advanced. Services › Unbound DNS › Query Forwarding.
MikroTik /ip route add dst-address=198.51.100.0/24 gateway=192.0.2.10 /ip dns static add name=cloud.internal type=FWD forward-to=192.0.2.10 match-subdomain=yes

Menu names move between versions; the fields stay the same.

Server Forward cloud.internal to the node
Pi-hole, dnsmasq server=/cloud.internal/192.0.2.10 (Pi-hole 6: Settings › All settings › misc.dnsmasq_lines)
AdGuard Home Upstream DNS servers: [/cloud.internal/]192.0.2.10
Technitium A Conditional Forwarder zone cloud.internal to 192.0.2.10, DNSSEC validation off for it
Unbound See below
BIND See below

Unbound:

server:
domain-insecure: "cloud.internal"
private-domain: "cloud.internal"
forward-zone:
name: "cloud.internal"
forward-addr: 192.0.2.10@53

BIND:

options {
validate-except { "cloud.internal"; };
};
zone "cloud.internal" {
type forward;
forward only;
forwarders { 192.0.2.10 port 53; };
};

.internal is not in the public DNS, so a validating resolver treats the node’s answers as forged: exempt the domain from DNSSEC validation, as above. Rebind protection may also drop private addresses: allow them for the domain.

OS Route DNS
Linux sudo ip route add 198.51.100.0/24 via 192.0.2.10 systemd-resolved: DNS=192.0.2.10 and Domains=~cloud.internal in a drop-in
macOS sudo route -n add -net 198.51.100.0/24 192.0.2.10 /etc/resolver/cloud.internal containing nameserver 192.0.2.10
Windows (admin PowerShell) route -p add 198.51.100.0 mask 255.255.255.0 192.0.2.10 Add-DnsClientNrptRule -Namespace ".cloud.internal" -NameServers "192.0.2.10"

A route on one machine works only on the node’s own network.

Without any DNS forward, a hosts-file line covers the fixed names:

192.0.2.10 stratum.cloud.internal

Load balancer and instance names come and go, so they need the forward.

Terminal window
dig +short @192.0.2.10 stratum.cloud.internal # 192.0.2.10
dig @192.0.2.10 example.com | grep status # REFUSED: the node is not a recursive resolver
Symptom Cause
dig @node answers, the LAN resolver says SERVFAIL DNSSEC validation: exempt the domain.
Empty answer through the LAN resolver Rebind protection: allow private answers for the domain.
A floating IP answers from the node’s network, not from another VLAN The router’s firewall.
Pings work, connections hang Half-seen connections on the router; see “Any router”.
The route is there, the instance still does not answer Its security group does not allow the traffic.