Documentation Architecture and Security

Architecture and Security

A document for anyone deciding whether to let L7 into their infrastructure: how the system is built, what it sees and what it doesn't, and what happens in various bad scenarios.

For security teams and technical directors ~8 min

1Components

Browser extension. 38 KB of vanilla JavaScript, unminified and unobfuscated — the code can be read end to end. It steers routing through the browser's own mechanisms: PAC in Chrome, the Proxy API in Firefox. It needs no administrator rights, installs no drivers, and changes neither system routes nor DNS.

Gateway. An 8 MB Go binary with no dependencies and no configuration files. It receives every setting and certificate from the dashboard over a secure channel and applies them on the fly. State is kept locally so it survives restarts and loss of connectivity.

Control Plane (CP). The web interface and API. Holds the configuration, hands settings to gateways and extensions, and keeps track of devices and limits.


2The path of a request

Browser ──TLS──► Gateway ──TLS──► Target server
   │
   └── unprotected domains ──► straight out to the internet
  1. Using the token, the extension receives the list of protected domains and the routing rules.
  2. The browser sends requests for those domains to the gateway via CONNECT, and everything else directly.
  3. The gateway checks the connection, resolves the name with its own resolver (honouring any IP and port overrides the administrator set) and opens a connection to the target server.
  4. From there the gateway only shuffles bytes between sockets.

The key consequence: the route is chosen per domain, not globally for the browser. Exactly what the token lists goes through the gateway.


3Device identity

A token is an invitation, not an identity document. The identity in this system is the device.

On installation the extension registers and receives a device identifier (dev_id) and a secret key. They're stored apart from tokens and don't reset when browser data is cleared — only when the extension is removed.

Every request to the API carries:

  • the device identifier
  • a timestamp
  • an HMAC-SHA256 signature

That yields three effects:

The API tells users of one token apart. A single token handed to three auditors is three distinct devices, with separate statistics and separate revocation.

Guessing tokens gets hard. The API can't be called anonymously: it takes a registered dev_id with a valid signature. Guessing attempts are tied to a specific device and cut off by device, not by an IP that's trivial to change.

Replayed requests don't work. The timestamp inside the signature protects against replay attacks.


4What protects a token

Five characters in the base58 alphabet (case significant) are an access identifier, not the only barrier. Even knowing the token, an outsider gets nothing, because:

  • the API can only be called from a registered device with a valid signature;
  • the number of activations is limited — once it's used up, no new device connects;
  • a token can have an activation window, outside which it doesn't work;
  • a token can be password-protected: the configuration downloads encrypted and won't decrypt without the password;
  • every device that connected is visible to the administrator and revocable on its own.

Password-protected tokens start with a capital character — it's visible in the spelling, so the password is expected right away.

Domain-level policies

Security requirements can be attached to the resource itself rather than to every token:

  • Protected token only — any token that includes such a domain must have a password. The dashboard won't let you create one without.
  • Private session only — a token with such a domain is forced into the extension's private mode: when the browser closes, the token and configuration are forgotten.

This is protection against human error: the mark is set once on a sensitive resource and applies to every future token, no matter who creates it or how much of a hurry they're in.

Policies are applied fail-closed, but without breaking access that already works: a protected domain can't be added to an unprotected token, and if the policy is turned on later, the domain becomes disabled inside existing tokens and can only be enabled once the requirement is met. Only the workspace owner and an administrator may change domain policies; a manager may not.

Separately, a domain can be hidden from the list in the extension — access works, but the resource isn't shown in the user's interface. Useful for technical domains the user never addresses directly.


5Gateway invisibility

The gateway answers no one except registered devices, and tells nothing about itself.

A unique address per device. Each device connects to the gateway under a host name of its own. Public DNS and the certificate contain only a wildcard — specific names are published nowhere. This matters because of Certificate Transparency: per-device certificates would mean a public list of every device, and a wildcard rules that leak out.

Pre-authorisation by SNI. The gateway checks the host name in the TLS handshake before anything else. If the name isn't expected, the connection is dropped: no ServerHello, no certificate, no TLS alert. The alert type is a fingerprint in itself, so it isn't sent.

The same reaction to any garbage. An ordinary HTTP request and invalid TLS both get the same dropped connection — you can't tell from the response which protocol the port expects.

IP banning. The source of a failed probe goes into a block list.

What a scanner sees: the port accepts a TCP connection. Nothing else — no banner, no certificate, no error code.


6Traffic encryption

Public sites: end-to-end encryption. The gateway routes by SNI and doesn't terminate TLS. The session is encrypted between the browser and your server; the gateway sees the domain name and the number of bytes transferred, but not the content. It cannot technically decrypt the traffic — it has no keys.

Internal services over HTTP: termination on your side. If a service runs without TLS (Grafana on 127.0.0.1:3000, say), the gateway is placed on the same machine or in the same network and terminates TLS locally, reaching the service over the loopback or a private address. The unencrypted leg never leaves your machine or your network.

In both cases, plaintext traffic never travels over public networks.


7Settings sync

Gateways receive their settings from the dashboard over a persistent connection.

Incrementally. Only changes are transmitted, not the full configuration of every user. That keeps application fast regardless of the size of the installation.

On the fly. New settings apply without a restart and without dropping current connections. If a user is given more traffic while downloading a file, the download won't break.

With state preserved. The gateway stores its configuration locally and keeps working when it loses contact with the dashboard — including across a server reboot.


8Revoking access

Revoking a device or changing limits reaches the gateways within seconds and applies immediately: restarting the browser won't help the user.

An important limitation. If a gateway is unreachable from the dashboard at the moment of revocation, the change applies once the connection is restored. Gateway autonomy is what protects you from downtime when something breaks on our side, but it also means the propagation window for a revocation equals the time it takes the connection to come back. Under normal conditions that's seconds.


9Failure modes

The dashboard is unavailable. Gateways keep working with the last known configuration. New devices can't connect, existing access continues. Setting changes apply once it's back.

A gateway is unavailable. Protected sites don't open for the people routed through that gateway. The rest of the browser's traffic is unaffected. Domains can be switched to another gateway in the dashboard.

The extension was removed. Access stops and nothing is left in the system. Installing it again requires activating a token again.

A user lost their device. Revoke its dev_id — access stops, and other users of the same token are unaffected.


10What we can and cannot see

We can see:

  • which domains devices connected to, and when
  • the volume of traffic transferred
  • device identifiers and statistics on their activity
  • gateway scanning events (protection telemetry)

We cannot see:

  • the content of traffic to public sites — it's encrypted end-to-end with TLS
  • passwords, cookies, form data, page content
  • traffic to domains that aren't in any token — it doesn't pass through our infrastructure at all

With a self-hosted gateway we can't see: any of the traffic whatsoever — it doesn't pass through our infrastructure in any form. In that case the dashboard exchanges nothing with the gateway but configuration and statistics.


Known limitations

An honest list, so you don't spend time finding out:

  • Browser HTTP/HTTPS only. SSH, databases and CLI access are not supported. A client for TCP-over-HTTPS is planned.
  • The gateway must be reachable from outside. Working behind NAT without port forwarding isn't possible.
  • ECH isn't used. Browsers don't apply Encrypted Client Hello to proxy connections, so an observer on the path (an ISP, a corporate DPI box) sees the host name a device uses to reach the gateway. The name is pseudonymous and useless without the device's keys.
  • One domain, one route at a time within a browser.