Hi there,
Just trying to get to the bottom of this after 2 days working on it. UPDATE: We were able to work through the niggles.
Still I am getting 401 No Ticket despite there being a VNC Ticket from vncproxy passed into vncwebsocket by noVNC (via path), and a cookie set with PVE Ticket I think too. UPDATE: No Ticket is to do with Access Ticket for PVE itself. This needed fine-tuning to work through.
Then there is novnc_router.php which adds the cookie locally for the ACL-restricted 'vnc' user on PVE, then routes to noVNC HTML file for the connection. Passed in to the file is the PVE Ticket, VNC Ticket, Server IP and Request Path.
We had to change our approach to be same-domain-only due to anti-CSRF (cookies can extend to subdomains only), update DNS to let that reflect, and then work through encoding the VNC Ticket properly to make it survive to pve-api-daemon.
noVNC then correctly has the Web Socket config with 1.2.3.4, port 8006, and path:
Firefox can’t establish a connection to the server at wss://1.2.3.4:8006/api2/json/nodes/syd-pvetest/qemu/103/vncwebsocket?port=5900&vncticket=PVEVNC%3A648F10... due to 401 No Ticket. The WHMCS and Proxmox are on different "domains" (Proxmox is only on an IP) but cookie error was same without adding 5th param to setrawcookie().
Update 1: We had to change how the cookie was being set for this to be worked through. And of course, anti-CSRF means same-domain.
Update 2: We then had a PVEVNC Ticket Invalid style response. This turned out to be due to a need to twice-encode the VNC Ticket.
Update 3: We had to change the noVNC query strings to include autoconnect=true and encrypted=true, & pass the password in.
Ref: (dual-encode) https://forum.proxmox.com/threads/4...ermission-denied-invalid-pvevnc-ticket.34144/
Ref: (moving to "vnc" user from "root" re: security) https://github.com/ZzAntares/ProxmoxVE/issues/17#issuecomment-688937674
Ref: (Invalid VNC Ticket - re: encoding) https://forum.proxmox.com/threads/401permission-denied-invalid-pvevnc-ticket.110961/
Ref: (cookie needed, class can't do token) https://forum.proxmox.com/threads/working-with-api-getting-401-no-ticket.75108/
Many people online seem to just revert to using iframe of the Proxmox VE GUI, and I see why. Finally we got it working.
Cheers,
Linux
Just trying to get to the bottom of this after 2 days working on it. UPDATE: We were able to work through the niggles.
Still I am getting 401 No Ticket despite there being a VNC Ticket from vncproxy passed into vncwebsocket by noVNC (via path), and a cookie set with PVE Ticket I think too. UPDATE: No Ticket is to do with Access Ticket for PVE itself. This needed fine-tuning to work through.
PHP:
function pvewhmcs_noVNC($params) {
$serverip = $params["serverip"];
$serverusername = 'vnc';
$serverpassword = Capsule::table('mod_pvewhmcs')->where('id', '1')->value('vnc_secret');
$proxmox=new PVE2_API($serverip, $serverusername, "pve", $serverpassword);
if ($proxmox->login()) {
# Get first node name.
$nodes = $proxmox->get_node_list();
$first_node = $nodes[0];
unset($nodes);
$guest=Capsule::table('mod_pvewhmcs_vms')->where('id','=',$params['serviceid'])->get()[0] ;
$vm_vncproxy=$proxmox->post('/nodes/'.$first_node.'/'.$guest->vtype.'/'.$params['serviceid'] .'/vncproxy', array( 'websocket' => '1' )) ;
// Get both tickets prepared
$pveticket = $proxmox->getTicket();
$vncticket = $vm_vncproxy['ticket'];
// $path should only contain the actual path without any query parameters
$path = 'api2/json/nodes/' . $first_node . '/' . $guest->vtype . '/' . $params['serviceid'] . '/vncwebsocket?port=' . $vm_vncproxy['port'] . '&vncticket=' . urlencode($vncticket);
$url = '/modules/servers/pvewhmcs/novnc_router.php?host=' . $serverip . '&pveticket=' . urlencode($pveticket) . '&path=' . urlencode($path) . '&vncticket=' . urlencode($vncticket);
$vncreply='<center><strong>Console (noVNC) prepared for usage. <a href="'.$url.'" target="_blanK">Click here</a> to open the noVNC window.</strong></center>' ;
return $vncreply;
} else {
$vncreply='Failed to prepare noVNC. Please contact Technical Support.';
return $vncreply;
}
}
Then there is novnc_router.php which adds the cookie locally for the ACL-restricted 'vnc' user on PVE, then routes to noVNC HTML file for the connection. Passed in to the file is the PVE Ticket, VNC Ticket, Server IP and Request Path.
We had to change our approach to be same-domain-only due to anti-CSRF (cookies can extend to subdomains only), update DNS to let that reflect, and then work through encoding the VNC Ticket properly to make it survive to pve-api-daemon.
PHP:
<?php
// FILE: novnc_router.php
// TASK: Take WHMCS request, add browser cookie, then redirect to noVNC
if (isset($_GET['pveticket']) && isset($_GET['host']) && isset($_GET['path']) && isset($_GET['vncticket'])) {
$pveticket = $_GET['pveticket'];
$vncticket = $_GET['vncticket'];
$host = $_GET['host'];
$path = $_GET['path'];
// Get the requesting hostname/domain from request
$whmcsdomain = parse_url($_SERVER['HTTP_HOST']);
$domainonly = preg_replace("/^(.*?)\.(.*)$/","$2",$whmcsdomain['path']);
setrawcookie('PVEAuthCookie', $pveticket, 0, '/', $domainonly);
// Create the final noVNC URL with the re-encoded vncticket
$hostname = gethostbyaddr($host);
$redirect_url = '/modules/servers/pvewhmcs/novnc/vnc.html?autoconnect=true&encrypt=true&host=' . $hostname . '&port=8006&password=' . urlencode($vncticket) . '&path=' . urlencode($path);
header('Location: ' . $redirect_url);
exit;
} else {
echo 'Error: Missing required info to route your request. Please try again.';
}
?>
noVNC then correctly has the Web Socket config with 1.2.3.4, port 8006, and path:
api2/json/nodes/syd-pvetest/qemu/103/vncwebsocket?port=5900&vncticket=PVEVNC%3A648F1097%3A%3ALF3XL%2FdXR%2FDhfXJMCPSduSCYkKEQn6m4lTkdnfQe9bSvCBQUFxaehjdyhhCd0EavucnmcTRZndnQPaLKSlWzSaTpb4yEhL%2B8rvuw%2Fec%2BNLPMh7JOin7vSiQJR2nJ%2BGtO%2BYPMXV9aD4Ib0vzRwmcrjx21u387nnQTX%2Bof0Ap8L0u3xN1XCcabKIMRDwvMMt9Xd5hX7dwg%2BHVufzMarCr2surgkJk7pRDIXB5VzHDBd6%2FQDoD7t29uhsbboY94vVwNA0n4cn2wF0gqqnKE01eUQOm0OdGPE%2BvPpjSxIRkNzSnNeI2PoJ1vLZX%2BOluNUC9KGW2J27LszC78KEKzrvZcqQ%3D%3D
Firefox can’t establish a connection to the server at wss://1.2.3.4:8006/api2/json/nodes/syd-pvetest/qemu/103/vncwebsocket?port=5900&vncticket=PVEVNC%3A648F10... due to 401 No Ticket. The WHMCS and Proxmox are on different "domains" (Proxmox is only on an IP) but cookie error was same without adding 5th param to setrawcookie().
Update 1: We had to change how the cookie was being set for this to be worked through. And of course, anti-CSRF means same-domain.
Update 2: We then had a PVEVNC Ticket Invalid style response. This turned out to be due to a need to twice-encode the VNC Ticket.
Update 3: We had to change the noVNC query strings to include autoconnect=true and encrypted=true, & pass the password in.
Ref: (dual-encode) https://forum.proxmox.com/threads/4...ermission-denied-invalid-pvevnc-ticket.34144/
Ref: (moving to "vnc" user from "root" re: security) https://github.com/ZzAntares/ProxmoxVE/issues/17#issuecomment-688937674
Ref: (Invalid VNC Ticket - re: encoding) https://forum.proxmox.com/threads/401permission-denied-invalid-pvevnc-ticket.110961/
Ref: (cookie needed, class can't do token) https://forum.proxmox.com/threads/working-with-api-getting-401-no-ticket.75108/
Many people online seem to just revert to using iframe of the Proxmox VE GUI, and I see why. Finally we got it working.
Cheers,
Linux
Last edited: