Relays, ports and firewalls

When two devices cannot reach each other directly, a member of your own network passes their traffic on. This page also lists the ports juist uses and what to open where.

What a relay does #

juist usually gets a direct tunnel through NAT. It fails only if both devices sit behind symmetric NAT, a strict kind that picks a new port for every destination. Then the two need a relay.

A relay is a member with a public address, such as a VPS, that passes traffic between devices that cannot reach each other. No third party ever relays your traffic. Only members can use the relay, and it sees only encrypted WireGuard traffic.

A relay also helps with invites. When you run juist invite on a laptop behind NAT, the invite also waits at the relay, and the link names the relay, so a new device can join from anywhere (Invites). The invite’s secret never reaches the relay.

Setting up a relay #

1on vps, the relay

Join the network, then open the ports with ufw:

sudo juist join 'juist:…'
sudo ufw allow juist && sudo ufw allow juist-relay

Or, with firewalld:

sudo firewall-cmd --permanent --add-service=juist --add-service=juist-relay && sudo firewall-cmd --reload
2on an admin's device

Give the VPS the role relay:

juist grant vps relay

The Relays line in juist status then counts it as available.

juist revoke vps relay takes the role away. It is best to give the role to two or more devices with public addresses. In a network of more than two devices, juist health warns as long as no device may relay.

A relay on 443 #

A relay can also serve a public name on port 443, like any HTTPS server. A device on a network that lets nothing else out reaches the relay there, either by itself or in HTTPS-only mode.

3on your DNS

Point a name such as relay.example.org at the relay, with an A record, and an AAAA record if the relay has IPv6.

4on vps, the relay

Have the relay serve the name:

sudo juist set --relay-name relay.example.org

juistd listens on 443/tcp at the relay’s addresses, ufw or firewalld let it in, and Let’s Encrypt issues a certificate for the name. juist status then says:

  Relay name    relay.example.org, on 443
  • Every device learns the name from the relay’s announcement.
  • Port 443 needs a privilege only root can give. sudo juist set gives juistd CAP_NET_BIND_SERVICE for this alone, through a systemd drop-in. sudo juist set --relay-name "" takes it away with the name.
  • On FreeBSD, juistd’s helper binds 443 only while root’s permission is in place and no other program listens on 443. If pf runs, it must let the traffic in.
  • If the name is gone but the privilege remains, juist health warns, and juist reset takes the privilege away.
  • Members use the name only once the server there proves it is this relay.
  • If the relay is also the network’s ingress, the ingress holds 443 and passes the name’s connections to the relay. Without --relay-name, it serves relay.DOMAIN, which the domain’s wildcard record already points at the ingress. relay is then no name to publish.
  • If several ingresses relay, one of them takes relay.DOMAIN, as juist status there says. Give the others their own names, and point relay.DOMAIN at that one alone.
  • A CAA record for the name must allow Let’s Encrypt.
  • On a device in several networks, only the default network’s juistd serves a name on 443.

Ports #

PortForOpen it where
41643/udpWireGuard and path discoverya device with a public address
41645/tcp, 41645/udpthe relay, and the STUN replies members use to measure ita device granted relay
443/tcpthe relay under its public namea relay with a name; juist set --relay-name opens it
41642/tcpaccepting an invite by code on the LANthe inviting device, while juist invite runs
443/tcp, 443/udp, 80/tcpthe names devices publish, over TLS and QUICa device granted ingress; juist ingress serve opens them
the TCP ports names are published onthose namesevery ingress; it opens and closes them as names are added and removed

Devices behind NAT need no open ports. Link invites need none either: if the new device cannot reach the inviting device directly, the two meet through a relay right away, or through the public DHT within about a minute.

A device in several networks runs one juistd per network. The n-th one uses these ports plus 10·n, for example 41653/udp for juistd@juist1.

Firewalls #

The packages install ufw and firewalld profiles named juist, juist-relay, juist-relay-443, juist-invite and juist-ingress. The profiles cover the first network’s ports; juist status gives the port numbers for the others.

Log sync runs inside the tunnel, on TCP 41644 on juist0 (41654 on juist1, and so on). The packages let it in if ufw or firewalld runs. A firewall you configured by hand must let it in too. Otherwise the device keeps its tunnels but misses changes to the network, removals included, and juist health reports this. An exit node also answers DNS there, on UDP and TCP 41646.

Note

Upgrading from a build whose juist profile opened every port: ufw keeps the old ports until sudo ufw app update juist, while firewalld narrows juist to 41643/udp right away. In both cases, a relay needs juist-relay added.

Running without public helpers #

By default, juistd asks public STUN servers (Google, Cloudflare) for its public address, and uses the public BitTorrent DHT to find members it lost track of. Both see addresses, never contents.

Once you have a relay of your own, the network can run without either. On every device, run:

sudo systemctl edit juistd

and enter:

[Service]
ExecStart=
ExecStart=/usr/bin/juistd --home /var/lib/juist --socket /run/juist/juistd.sock --tun juist0 --no-dht --no-stun

Devices then find each other on the LAN and through members they already know. The relay tells each device its public address, and invite links meet through it. man juistd lists every option.

Troubleshooting #

juist health saysWhat to do
no tunnel traffic from …open 41643/udp on a device with a public address, or grant one relay
no device reaches this relayopen 41645/tcp and udp on the relay, and in any firewall in front of it
no device may relayrun juist grant DEVICE relay for a device with a public address
no certificate for relay.example.org yetpoint the name at the relay, and let 443/tcp reach it
the relay cannot take 443another program holds 443 there, or juistd lacks the capability juist set grants
members are not told of …: this device does not relaygrant the device relay: juist grant DEVICE relay
log sync … fails in the tunnellet juist0 through the other device’s firewall, as the hint says
no answer from …the device is offline, or its 41643/udp is closed