VNC über API: 401 No Ticket

Vengance

Renowned Member
May 21, 2016
271
12
83
34
Hallo,

Ich versuche aktuell über die API eine VNC Konsole zu öffnen.


PHP:
public function getTicket()
    {
        $response = Http::asForm()->post('https://' . $this->server->hostname . ':8006/api2/json/access/ticket', [
            'username' => 'root',
            'password' => 'meinpasswort',
            'realm' => 'pam',
        ]);

        return json_decode($response)?->data?->ticket;
    }
    public function getVncConsole()
    {
        $ticket = $this->getTicket();
        $config = json_decode(Http::withToken($this->apikey)->asForm()->post('https://' . $this->server->hostname . ':8006/api2/json/nodes/' . $this->server->node . '/qemu/' . $this->node->vm_id . '/vncproxy', [
            'websocket' => 1,
        ]));

        $websocket = json_decode(Http::withToken($this->apikey)->asForm()->get('https://' . $this->server->hostname . ':8006/api2/json/nodes/' . $this->server->node . '/qemu/' . $this->node->vm_id . '/vncwebsocket', [
            'vncticket' => $ticket,
            'port'      => $config->data->port
        ]));

        setcookie('PVEAuthCookie', $ticket, 0, '/', 'meinedomain.com', false);

        $src_href = 'https://' . $this->server->hostname . ':8006/?console=kvm&novnc=1&node=' . $this->server->node . '&resize=1&vmid=' . $this->node->vm_id . '&path=api2/json/nodes/' . $this->server->node . '/qemu/' . $this->node->vm_id . '/vncwebsocket/port/' . $config->data->port . '/vncticket/' . $ticket;
        ray($src_href);
        return '<iframe src="' . $src_href . '" frameborder="0" scrolling="no" class="w-full rounded-lg shadow" width="800px" height="600px"></iframe>';
    }


Ausgabe:


Code:
https://meinedomain.com:8006/?console=kvm&novnc=1&node=dev1&resize=1&vmid=112&path=api2/json/nodes/dev1/qemu/112/vncwebsocket/port/5900/vncticket/PVE:root@pam:62F3DAC2::HXKXFEd4wViw2iBGXECXSe7Z71/I4wq0qywjeUwE/Ew7+VHTiMzqP4mvPrzCHRyfC6AhHTqBbKPYzCApNYP9/fev0Ha9EKoTGqyQFwvzav5GaEWegH7sSpO+C13vZ6lAY4Wr0dNxytuCeE1ryMwJ6wd4+zcUPAubQIbAgl3iDCtSDNQaWtX4Uo79ZcFe7Zf52KP+Y3wbdjyqNYOmPXjiMDsYNb8PO7bxARTixWqkHCF3mSry69lKT91PhZxEw5vmnmZlVA/sAVeKQQmzKO/yYZuwjzDYRaiqKz4ALga2Sdkd6WLau07Sxe2VCprJ5IygCwTsHD6cjwId5RRuiMDt/g==

Wenn ich das dann in ein iFrame einbette bekomme ich leider die Fehlermeldung 401 No Ticket.

Hat jemand eine Idee was ich falsch mache?


Danke!
 
wird der cookie 'PVEAuthCookie' auch tatsächlich mitgeschickt im iframe? ist zwar jetzt geraten, aber vielleicht fehlt der port beim cookie setzen? (also meinedomain.com vs meinedomain.com:8006 im cookie)
 
Muss die Domain zwingend identisch zwischen dem Panel und proxmox Server sein?

Das hatte ich zumindest irgendwo gelesen, und in meiner testzmgebung sind die Domains leider unterschiedlich.

Laut der dev Konsole wird auch kein Cookie gesetzt
 
Muss die Domain zwingend identisch zwischen dem Panel und proxmox Server sein?
weiß zwar nicht genau was du meinst, aber das iframe muss ein gülitges pve cookie haben, da zT auch api calls abgesetzt werden und der websocket call ansich auch ein gültiges pve ticket braucht (zusätzlich zum vncticket)
 
Muss die Domain zwingend identisch zwischen dem Panel und proxmox Server sein?
https://www.rfc-editor.org/rfc/rfc6265#section-4.1.2.3
The user agent will reject cookies unless the Domain attribute
specifies a scope for the cookie that would include the origin
server. For example, the user agent will accept a cookie with a
Domain attribute of "example.com" or of "foo.example.com" from
foo.example.com, but the user agent will not accept a cookie with a
Domain attribute of "bar.example.com" or of "baz.foo.example.com".

NOTE: For security reasons, many user agents are configured to reject
Domain attributes that correspond to "public suffixes". For example,
some user agents will reject Domain attributes of "com" or "co.uk".
(See Section 5.3 for more information.)
d.h. bau this->server->hostname zu foo.meinedomain.com um, dann kannst Du nen Keks für meinedomain.com setzen.

Oder Du bastelst auf meinedomain.com ein Skript rein, das einen per URL übergebenen Wert als Cookie setzt.
 
Eine Alternative bietet hier unter anderem auch Websockify mit einem selbst gehosteten noVNC. Um 8006 nicht extern zu exposen nutzen wir eine VM "console.domain.com", wo wir den Websockify Dienst via 443 (WSS) hosten. Dieser Console Server wiederum hat Zugriff auf Datacenter Level (TCP, 5900:5999).

Via PHP lässt sich dann via Proxmox API das VNC-Ticket generieren, in der zugehörigen Redis Datenbank von Websockify hinterlegen.
Hierzu nutzen wir neben dem VNC-Ticket noch einen intern generierten Token für die Verbindung zwischen Client und Console Server, um die Ziel-VNC-Verbindung zu steuern.

Redis DB:
Code:
# Key Custom Token                        # Value (Proxmox IP + VNC Port)
381e061e29400afdf98edfafd1a4ce4be574f988  PROXMOX_IP:5900

Proxmox öffnet die VNC-Ports nur dann, wenn eine VNC-Sitzung gestartet wird, sodass der Websockify Server keinen API-Zugriff hat und nur die VNC Ports benutzen kann. (Der Websockify Server benötigt keinen eingehenden TCP 8006 Zugriff)

Iframe SRC:
Code:
https://domain.com/novnc/1.4.0/vnc.html?host=console.domain.com&autoconnect=1&encrypt=1&path=?token={$token}&password={$proxmox.vnc.ticket|urlencode}

Wichtig: Das Ticket aus der Response von /qemu/{id}/vncproxy muss URL enkodiert werden.

Ergebnis:
- Kein exposed 8006
- PVE Cookie wird nicht für den Client benötigt
- WSS über 443
- VNC-Server hat nur den VNC Zugriff (5900:5999)
 
Last edited:

About

The Proxmox community has been around for many years and offers help and support for Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
We think our community is one of the best thanks to people like you!

Get your subscription!

The Proxmox team works very hard to make sure you are running the best software and getting stable updates and security enhancements, as well as quick enterprise support. Tens of thousands of happy customers have a Proxmox subscription. Get yours easily in our online shop.

Buy now!