alvr-org / ALVR

Stream VR games from your PC to your headset via Wi-Fi
MIT License
5.35k stars 480 forks source link

Manual registration of clients #372

Closed zarik5 closed 3 years ago

zarik5 commented 3 years ago

Support specifying the IP of clients not discoverable in the local network.

Background: on the server, clients are identified by hostname. The hostname is in the format X.client.alvr where X is a 16 bit integer. The client list is stored in the field clientConnections in the session. The structure and fields are defined here https://github.com/alvr-org/ALVR/blob/master/alvr/common/src/data/session.rs (field names are converted to camelCase when accessed from javascript).

Armarr commented 3 years ago

@zarik5 I'm working on the UI for this but I'm confused as to why you'd need a hostname and device name input field. Do I understand correctly that you want to allow users to add IP addresses to an existing trusted device? But in that case you already know the host name and would only need to link a new IP to it. And if you want to add a completely new device then why doesn't ALVR just generate a hostname for me if there's a standard format (X.client.alvr) afbeelding

zarik5 commented 3 years ago

Thanks for working on it! The hostname is generated by the client, and usually broadcasted to the server (when found in the local network). The hostname is used to generate a private key and a certificate on the client side (both of which are unused as of now). The device name has no functional purpose other than for display.

I report here an example of the client info:

    "44945.client.alvr": {
      "deviceName": "Oculus Quest 2",
      "lastLocalIp": "192.168.4.85",
      "manualIps": [],
      "trusted": true,
      "certificatePem": "-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----\r\n    " // can be null
    }

When adding a new unknown client, the UI should send a POST request at /client/add with the body ["<device name>", "<hostname>", "<ip>"]. When adding a manual IP to an existing client, the UI should send a POST request at /client/trust with the body ["<hostname>", "<new ip>"]. To remove a manual IP the request should be /client/remove with body ["<hostname>", "<old ip>"].

Armarr commented 3 years ago

Would it be possible to display the Quest's IP address on the startup screen? I found this in an old repo, not sure if it would still work on v23

WifiManager wm = (WifiManager) context.getSystemService(WIFI_SERVICE);
wm.getConnectionInfo().getIpAddress();
DavisNT commented 3 years ago

Does currently (in current version of ALVR) ALVR server connect (send the first packet) to the client?

If not, how will the client "know" where to connect if client and server won't be on the same network?

What UDP/TCP ports (and in which directions) are used for communication between ALVR client and server currently?

zarik5 commented 3 years ago

If the server and client are on different networks, the UDP part of the handshake is completely skipped. The client listens for every TCP connection (regardless if it's local or remote). Basically the client behaves like a server and vice versa: the client has a certificate that the server must trust (the certificate is skipped in case of manual clients), then it's the client that listens for incoming connections.

DavisNT commented 3 years ago

Are video and controls afterwards streamed via TCP or UDP?

I am wondering - could this be made to work over the internet (with no/minimal preparations on headset side)? Although this is not my usage, but I suppose there could be people who would like to take their headsets to friends etc.

zarik5 commented 3 years ago

Are video and controls afterwards streamed via TCP or UDP?

For now, video, audio, tracking, etc are streamed throgh UDP. TCP is only for connection status signals.

I am wondering - could this be made to work over the internet (with no/minimal preparations on headset side)? Although this is not my usage, but I suppose there could be people who would like to take their headsets to friends etc.

I don't see any straightforward way. Also you still need to open the ports manually in the router

DavisNT commented 3 years ago

For now, video, audio, tracking, etc are streamed throgh UDP. TCP is only for connection status signals.

Sounds great! I would expect video/audio/tracking streamed over TCP to cause weird effects on packet loss (e.g. wifi glitches).

I don't see any straightforward way. Also you still need to open the ports manually in the router

Maybe with time it could be possible to implement a mode where headset connects to the server (then port openings could be made on PC side)... If there is some encryption/security in place, this might make ALVR quite usable over the internet (in the "visiting friends and bringing full blown PC VR experience" situations).

Are the client certificates currently validated? And are they used for authentication or is there also some encryption for the tracking signals (preventing a MITM attack to take over the PC)?

Can locally discovered and trusted clients (headsets) change their IP addresses freely without additional prompts for trust (assuming the certificates don't change)?

If the certificate is validated, maybe it would be worth to make the server (PC) to prompt for trust upon first connection with manually added client (headset) and then remember client's certificate?

zarik5 commented 3 years ago

Are the client certificates currently validated?

No, neither for authentication or encryption. This will be for a future update.

Can locally discovered and trusted clients (headsets) change their IP addresses freely without additional prompts for trust (assuming the certificates don't change)?

Yes, that was one of the reasons to switch to the new connection system in v14.

If the certificate is validated, maybe it would be worth to make the server (PC) to prompt for trust upon first connection with manually added client (headset) and then remember client's certificate?

Currently, local clients send their hostname and certificate as the first handshake packet though broadcasting. When you add a remote client you are trusting the hostname (but not the certificate since it is not specified, so no authentication can be performed). Authentication and encryption could be performed only if the client does first connect on a local network (to send the handshake packet), and then connect from a remote location. Receiving and trusting the certificate on the first connection sounds better but it isn't supported by the current connection system. I may have to make some changes.

Armarr commented 3 years ago

@zarik5 I'm getting 400 errors while testing the add and remove IP endpoints afbeelding

zarik5 commented 3 years ago

@Armarr You forgot the device name (before the hostname)

zarik5 commented 3 years ago

This can be closed. Thanks @Armarr!