## Understanding REALITY Let's take a snippet from a client config. This client is configured to use TCP as the transport and use `xtls-rprx-vision` flow. ```json "streamSettings": { "network": "tcp", "security": "reality", "realitySettings": { "show": false, "serverName": "example.com", "fingerprint": "chrome", "publicKey": "D2NF6TgQzdVp6AOJPt7A-_wstOFafTyfuj_jKK8G7lQ", "shortId": "c39502f5bfd54fe2", "spiderX": "" } } ``` Under the `realitySettings` field you'll see a number of fields. - The `publicKey` field will coincide with the `privateKey` field set on the server side. - The `shortId` is a field that can only contain one ID on the client, but many on the server side. - The `spiderX` field is unclear, but according to the source code, if left empty it is replaced with a `/` character. The most important fields are `fingerprint` and `serverName`. - The `fingerprint` field determines how REALITY will make the TLS stream appear on the wire. In the case of setting it to `chrome`, the TLS connections are real and are made to mimic the chrome browser. - Finally `serverName` is what dictates the contents of the SNI field used in the TLS client hello. This should match the domain within the `dest` field on the server side. ```json "streamSettings": { "network":"tcp", "security":"reality", "realitySettings": { "show": false, "dest": "example.com:443", "minClientVer": "1.8.3", "privateKey": "cKv649do0LvL6YRuPe9bJ-GxNkgok9dAUGnfyi39ZFw", "serverNames": [ "example.com" ], "shortIds": [ "c39502f5bfd54fe2" ] } } ``` On the server side, the fields are slightly different. - There's a `dest` field, which is where non-vless traffic is sent. This means that if someone were to initiate a request to your server using a non-vless protocol, such as https, then the raw data would simply be passed on to the server in the `dest` field. This would make your server look genuine, as the response received for non-vless traffic would match what is expected from the sni in the tls connection. - The `minClientVer` field can be useful to prevent old versions of reality from successfully using your server. - This time, `shortIds` is an array, which means you can potentially have many clients, each with different values, or perhaps use this as a way to migrate users to a new `shortId`. - The `serverNames` field is also an array, usually it would be something like `[ "www.example.com", "example.com" ]`. It also does not accept wildcards. There are other fields not included in the example above. They are less significant in my opinion. ##### Generate ShortIDs ```sh $ openssl rand -hex 8 c39502f5bfd54fe2 ``` Or ```sh $ sing-box generate rand --hex 8 422e5314fa59cb84 ``` ##### Generate public/private keypair ```sh $ xray x25519 Private key: cKv649do0LvL6YRuPe9bJ-GxNkgok9dAUGnfyi39ZFw Public key: D2NF6TgQzdVp6AOJPt7A-_wstOFafTyfuj_jKK8G7lQ ``` Or ```sh $ sing-box generate reality-keypair PrivateKey: ANXMr4PbVS8XD6xlbBwvtQQWNhFjn1QKs76qlVYmDH4 PublicKey: qxEMfK1mDK75xE7ZnUcYXMhR4tYTrB43AlbEgYmW00s ``` To recover the public key from the private key, the xray binary can do that. ```sh $ xray x25519 -i "ANXMr4PbVS8XD6xlbBwvtQQWNhFjn1QKs76qlVYmDH4" Private key: ANXMr4PbVS8XD6xlbBwvtQQWNhFjn1QKs76qlVYmDH4 Public key: qxEMfK1mDK75xE7ZnUcYXMhR4tYTrB43AlbEgYmW00s ``` The output of these commands is not identical, and there's no output format flag. So here's a script that turns the above into json at versions 1.8.3 and 1.3.5 of xray and sing-box. (the jq program must be installed) ```bash #!/bin/sh keys=`xray x25519` # keys=`sing-box generate reality-keypair` private_key=`echo "$keys" | sed -n '1p' | awk -F': ' '{print $2}'` public_key=`echo "$keys" | sed -n '2p' | awk -F': ' '{print $2}'` echo "{}" | jq --arg priv "$private_key" --arg pub "$public_key" '.["private_key"]=$priv | .["public_key"]=$pub' ``` ## misc Saw some tweets and translated some issues that suggest REALITY protocol is still kinda detectable. I mean obviously it's detectable through traffic patterns, but I didn't think the protocol itself is still obvious. In this [tweet](https://twitter.com/uo0sef/status/1675869182078996482) it's suggested that a badly configured REALITY bridge is easily fingerprint-able. Subsequent replies suggest that currently the best solution is to frequently rotate the keys and shortid. Apparently this is evidenced by another reply that essentially says "many are experiencing TLS handshake timeouts and when they regenerate their public and private keys, the issue is resolved. Either they're building a new inspection system or there's just problems in the network."