What relays solve
Section titled “What relays solve”When your exit server’s IP gets blocked, users lose access. A relay gives them a domestic entry point that is harder to block:
Client → Relay (domestic IP) → Exit server (abroad) → InternetCensors see traffic to a domestic IP. The relay forwards raw TCP to the exit; encryption is end to end between the client and the exit, so the relay never sees plaintext.
How relays work
Section titled “How relays work”A relay runs Realm, a small zero-copy TCP forwarder. It listens on port 443 (configurable) and forwards to the exit’s Reality listener. No Docker and no panel run on the relay.
Relays carry Reality traffic. XHTTP, WSS, and Hysteria2 stay on the exit’s own address and domain, and remain in the same subscription as alternatives.
Deploy a relay
Section titled “Deploy a relay”Deploy the exit first, then point a relay at it:
meridian relay add 203.0.113.10 --exit 198.51.100.10Meridian adds the relay to your topology and applies it:
- Prepares the relay server (packages, BBR, SSH hardening, a firewall that opens only SSH and the relay port)
- Installs Realm (version-pinned, SHA256-verified) as a systemd service
- Points the relay at the exit’s Reality listener
- Publishes the relay in every client’s subscription
| Flag | Default | Description |
|---|---|---|
--exit/-e EXIT | (required) | Exit server IP or name |
--name NAME | (auto) | Friendly name for the relay (e.g. ru-moscow) |
--port/-p PORT | 443 | Listen port on the relay server |
--sni HOST | exit’s target | Reality camouflage target for this relay; omit it to use the exit’s |
--user/-u USER | root | SSH user on the relay |
--ssh-port PORT | 22 | SSH port on the relay server |
--yes/-y | Skip confirmation prompts |
Example with all options
Section titled “Example with all options”meridian relay add 203.0.113.10 --exit 198.51.100.10 --name ru-moscow \ --port 443 --sni dl.google.com --user ubuntu --ssh-port 2222 --yesHow clients connect
Section titled “How clients connect”Existing clients receive the relay on their next subscription refresh, and their connection pages list it. New clients get it automatically:
meridian client add alice # relay includedManage relays
Section titled “Manage relays”meridian relay list # all relaysmeridian relay list --exit 198.51.100.10 # relays for one exitCheck a relay’s hops — each Realm service is running, each hop reaches the next, and the public entry accepts connections — then test real traffic through the whole route:
meridian check 203.0.113.10meridian testThe check also measures each leg: from every hop it downloads the exit’s camouflage site through the next hop, sending the same SNI clients send, and reports the connect time, the time to first byte, and how many bytes arrived. A transfer that freezes between roughly 8 and 32 KB is the signature of throttling on that leg and is reported as a warning; the usual fix is a relay host at a different provider (another network, or ASN). If the camouflage site’s home page is smaller than 32 KB, the leg check is inconclusive rather than passing.
To give a relay another camouflage SNI, for example when meridian test --probe reports its SNI blocked, change it in place. Meridian checks that the exit reaches the new site, shows the review, and applies it; the old name stops working at once, and apps switch at their next subscription refresh (every 6 hours) or a manual refresh. Pass the exit’s own SNI to make the relay follow the exit again:
meridian relay sni 203.0.113.10 dl.google.comTo retire a relay, remove the chains through it. Meridian shows what it will delete, asks for confirmation, and cleans up the Realm service, firewall rules, and published entry points; existing clients lose the relay on their next subscription refresh:
meridian relay remove 203.0.113.10Multiple relays
Section titled “Multiple relays”Attach several relays to one exit, for example in different cities or networks:
meridian relay add 203.0.113.10 --exit 198.51.100.10 --name ru-moscowmeridian relay add 203.0.113.11 --exit 198.51.100.10 --name ru-spbClients receive every relay in their subscription. For relay chains with more than one hop, use meridian setup.
Mobile whitelists
Section titled “Mobile whitelists”During some mobile internet restrictions in Russia, operators let through only an approved list of sites and addresses. Reports vary by operator, region, and week, and no operator publishes its list. Meridian does not detect or track whitelists; this section covers what you can set up today and what stays manual.
What deployers report
Section titled “What deployers report”- Networks differ. Some seem to look only at the server name (SNI) a connection announces. Others also check the destination IP. Where only the name is checked, a direct Reality path with an allowed name can pass. Where the IP is checked too, the first hop has to be an address on the list.
- Domestic cloud addresses are the usual first hop. Not every address from a provider is listed: people describe one subnet of a provider’s range being allowed while another from the same provider is not. Providers may also limit private customers, cap how often you can recreate a server, or shape bandwidth.
- Foreign CDN addresses are generally not allowed on mobile networks. Treat domain mode through Cloudflare as a fallback for home connections, not as a whitelist answer.
- The relay-to-exit link can be disrupted too. A relay that reaches users can still lose its connection to a foreign exit.
A relay on an allowed address
Section titled “A relay on an allowed address”Rent a small server on a domestic provider whose address is allowed on your users’ mobile networks. Community-maintained lists of allowed ranges exist, but only a test from a mobile connection while restrictions are active proves it. Then add it as a relay and give it an allowed name:
meridian relay add 203.0.113.10 --exit 198.51.100.10 --name ru-mobile --sni allowed.example.comWith --sni, only this relay’s entry in the subscription announces that name. Meridian gives the relay its own listener on the exit, reachable only from the relay’s last hop, and a Reality listener (same keys) that imitates the name. It routes only that name to Reality and sends everything else to that site, so a prober that reaches the relay without a valid key sees the site’s real certificate instead of a proxy answer. The exit’s own camouflage target and its other entries don’t change. The exit must reach the name with TLS 1.3 and HTTP/2; change it later with meridian relay sni RELAY NEW_SNI.
Then check the relay and test from the network that matters:
meridian check 203.0.113.10meridian testmeridian test from your own machine can’t tell you what a whitelisted mobile network allows. Try it on a real device on that network.
Pick an exit SNI
Section titled “Pick an exit SNI”--sni on meridian deploy and meridian node add sets the camouflage target for the exit’s direct Reality path. The target must be a site the exit can reach with TLS 1.3, and deploy checks real traffic through it and stops if none passes. Before deploying, check a candidate with meridian check IP --sni HOST. On a network that checks names only, an allowed name may let the direct path through, but whether a name works depends on the operator, so test each one.
What Meridian doesn’t do
Section titled “What Meridian doesn’t do”- It doesn’t tell you whether a relay’s IP is on any operator’s list, or whether restrictions are active.
- It doesn’t set up fronting through a domestic CDN. Domain mode is built and tested for Cloudflare.
- A relay carries Reality only. XHTTP, WSS, and Hysteria2 stay on the exit.
- It doesn’t tunnel through third-party calling or messaging services.
Troubleshooting
Section titled “Troubleshooting”Port conflict
Section titled “Port conflict”Another service is using the listen port on the relay. Check with ss -tlnp sport = :443 and stop it, or pick another port with --port 8443.
Firewall blocking
Section titled “Firewall blocking”Make sure the relay port is open in your cloud provider’s firewall or security group, not only in UFW.
Exit unreachable
Section titled “Exit unreachable”The relay must reach the exit’s Reality port. Run meridian test to check the route end to end, and meridian check EXIT to check the exit itself.
Relay service not running
Section titled “Relay service not running”On the relay server, list the forwarder services and read their logs. Relay hosts use neutral names (netfwd-* units, /etc/netfwd/ configs) so nothing on them names Meridian, Realm, or a relay:
systemctl list-units 'netfwd-*'journalctl -u 'netfwd-*' --no-pager -n 20