[SOLVED] NOVNC from remote

woodstock

Renowned Member
Feb 18, 2016
42
2
73
Hi,

I am also trying to setup an external NOVNC website using pve2_api.class.php from here:

https://github.com/CpuID/pve2-api-php-client/blob/master/pve2_api.class.php

My test lab consists of one proxmox node and one linux VM located in the proxmox subnet.
The VM has apache and PHP installed and NOVNC (unpatched) has been copied to /var/www/html.
Ports 8006 and 5900-5999 are allowed between the test lab and my workstation.
I can use NOVNC via proxmox GUI on my workstation without problems.

The website on the VM is hosting a small PHP script that does the API calls for login and vncproxy without errors. I received both, port and ticket. However, here I am stuck.

Is it ok to use NOVNC from http://kanaka.github.io/noVNC/ or do I have to use NOVNC with proxmox patches applied?

Can I copy the content from /usr/share/novnc-pve/ to my website and return a rewritten index.html.tpl to the browser? If so, what should be set as PVE.CSRFPreventionToken?

What http GET parameters do I have to append to the NOVNC window?

Many questions – I know. However, after searching the forum and reading whatever I could find about NOVNC, it seems to me that this is something many people are asking for without ever finding a solution.

Thanks
 
After a long time struggling, I finally found a solution to this.

But first of all many thanks to all forum posters also trying to get this working and sharing their results – that helped a lot.

The following is a brief description of my setup:

Starting point is my lab cluster with tree nodes (not required, but that’s what I already had):

pvelab1 - 192.168.1.101
pvelab2 - 192.168.1.102
pvelab3 - 192.168.1.103

First, you need a (virtual) server for installing nginx. I am using a debian VM on my proxmox lab cluster for that.
To keep the setup simple I gave that server an IP address within the clusters subnet: 192.168.1.10

Install all packages needed ...
Code:
apt-get install nginx-full openssl php5-fpm php5-curl


Since we need a SSL certificate for this to work, create a self-signed certificate:
Code:
mkdir -p /etc/nginx/ssl
openssl genrsa -out /etc/nginx/ssl/server.key 2048
openssl req -new -sha256 -key /etc/nginx/ssl/server.key -out server.csr
openssl x509 -req -days 3650 -in server.csr -signkey /etc/nginx/ssl/server.key -out /etc/nginx/ssl/server.crt


Then configure nginx:
Code:
nano /etc/nginx/sites-available/proxmox-gui
ln -s /etc/nginx/sites-available/proxmox-gui /etc/nginx/sites-enabled/


/etc/nginx/sites-available/proxmox-gui contains these lines:
Code:
#
# upstream to proxmox cluster
#
upstream pvelab {
    server 192.168.1.101:8006;
    server 192.168.1.102:8006 backup;
    server 192.168.1.103:8006 backup;
}

#
# private server with php supprt
#
server {

    listen 127.0.0.1:5555;
    root /var/www/html;
    index index.php;

    location ~ .php$ {
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        try_files $uri $uri/index.php;
    }
}

#
# public server with ssl
#   proxy two pve api methods (vncproxy and vncwebsocket)
#   and redirect ererything else to the local server
#
server {

    server_name _;
    listen 443;

    ssl_certificate_key /etc/nginx/ssl/server.key;
    ssl_certificate /etc/nginx/ssl/server.crt;
    ssl on;

    proxy_redirect off;

    location ~* .*/(vncproxy|vncwebsocket)$ {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_pass https://pvelab;
    }

    location / {
        proxy_pass         http://localhost:5555;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   Host $host;
    }

}


On debian I needed an additional line in /etc/nginx/fastcgi_params:
Code:
fastcgi_param  SCRIPT_FILENAME    $request_filename;


To complete the nginx/php5-fpm setup restart both:
Code:
service php5-fpm restart
service nginx restart


Now we need to copy the noVNC files from our proxmox server(s):
Code:
mkdir -p /var/www/html/novnc/locale
scp root@192.168.1.101:/usr/share/pve-manager/locale/* /var/www/html/novnc/locale/
scp -r root@192.168.1.101:/usr/share/novnc-pve/* /var/www/html/novnc/


The file index.html.tpl (copied in the previous step) needs to be patched.

Save the following as patch file index.html.tpl.patch:
Code:
--- index.html.tpl      2017-03-10 08:37:24.000000000 +0100
+++ index.html.tpl      2017-05-13 21:44:01.000000000 +0200
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 <head>
-    <title>[% nodename %] - Proxmox Console</title>
+    <title>noVNC</title>

     <meta charset="utf-8">

@@ -14,11 +14,9 @@
     <!-- Stylesheets -->
     <link rel="stylesheet" href="/novnc/include/base.css" />

-    [% IF langfile %]
-    <script type='text/javascript' src='/pve2/locale/pve-lang-[% lang %].js'></script>
-    [% ELSE %]
+
     <script type="text/javascript">function gettext(buf) { return buf; }</script>
-    [% END %]
+
     <script type="text/javascript">
 if (typeof(PVE) === 'undefined') PVE = {};
 PVE.UserName = '[% username %]';


And apply it with:
Code:
patch -d /var/www/html/novnc < index.html.tpl.patch


Now download the PHP API class:
Code:
wget -O /var/www/html/pve2_api.class.php https://raw.githubusercontent.com/CpuID/pve2-api-php-client/master/pve2_api.class.php


That file also needs to be patched.

Save the following as patch file pve2_api.class.php.diff:
Code:
--- /var/www/html/pve2_api.class.php    2017-05-15 10:53:02.572000000 +0200
+++ /var/www/html/pve2_api.class.php    2017-05-15 11:06:13.000000000 +0200
@@ -131,6 +131,14 @@
                setrawcookie("PVEAuthCookie", $this->login_ticket['ticket'], 0, "/");
        }

+       # returns the CSRFPreventionToken
+        public function getCSRFPreventionToken() {
+                if (!$this->check_login_ticket()) {
+                        throw new PVE2_Exception("Not logged into Proxmox host. No Login access ticket found or ticket expired.", 3);
+                }
+                return $this->login_ticket['CSRFPreventionToken'];
+        }
+
        /*
         * bool check_login_ticket ()
         * Checks if the login ticket is valid still, returns false if not.


Again apply the patch with:
Code:
patch -d /var/www/html < pve2_api.class.php.diff


The last thing remaining is to create a PHP script that returns the noVNC page.
As this is only for demonstration purposes I included everything hard coded.

Save the following as file /var/www/html/index.php:
Code:
<?php

require("pve2_api.class.php");

$nodeaddress = "192.168.1.101";
$nodename = "pvelab1";
$nodeport = 8006;

$user = "testuser";
$pass = "testpass";
$auth = "pve";

$vmname = "test";
$vmid = 100;

$pve2 = new PVE2_API($nodeaddress, $user, $auth, $pass, $nodeport);

if ($pve2->login()){

    $pve2->setCookie();

    $userauth = sprintf("%s@%s", $user, $auth);
    $token = $pve2->getCSRFPreventionToken();

    $file = file_get_contents('novnc/index.html.tpl', FILE_USE_INCLUDE_PATH);
    $searchTerms = array ( '[% vmname %]', '[% username %]', '[% token %]' );
    $replacements = array ( $vmname, $userauth, $token );

    print(str_replace( $searchTerms, $replacements, $file));

} else {
    print("Login to Proxmox Host failed.\n");
}

?>


That’s it! You now should be able to start a noVNC session with the URI parameter you already know from the Proxmox GUI:

https://192.168.1.10/index.php?console=kvm&novnc=1&vmid=100&vmname=test&node=pvelab1&resize=1

Open issues:

Right now all the actions in the noVNC window (Reset, Shutdown, ...) show an error.
They seem to need additional API methods, but thats something I will sort out some time later ...

Hope this saves someone some time :)
 
Hello, I don't have a file index.html.tpl on my proxmox server, would you share yours?

Hello,

This file seems to be only on 5.x Beta servers and that is what I did install for my tests:

PVE version: proxmox-ve: 5.0-2 (running kernel: 4.10.1-2-pve)

I did not see that until now. File has been attached.
 

Attachments

  • index.html.tpl.zip
    2.2 KB · Views: 105
  • Like
Reactions: hambali
When you set up the cookie like you did, what happens if the user tries to open the Proxmox web interface directly?

My Proxmox nodes are placed behind a firewall and I do not allow direct access (to port 8006).
Management can only be done via VPN and VM traffic is separated and goes unfiltered.

If you do allow direct access the user will be able to login and do whatever he is allowed to do.

What do you want to achieve and what does your setup look like?
 
At the moment I am just testing Proxmox. I have a single node on public access (with just some testing VMs, no production). I just wanted to know how you deal with possible vulnerabilities that might open.

What your plan is to set a cookie inside the user's PC, which would allow him to gain the same access as $user = "testuser"; has. If he then gains somehow access to the Proxmox, it might be abused. Either way, I still didn't find a suitable solution for this. I guess the proper way to do this would be to create a Proxmox user for each client with access only to a set of VMs and then use this user in your script for login. This sounds very tedious, so perhaps one user with access to all VMs with Console privilege only should suffice.
 

@woodstock, you are great man! Last week I was looking for something like that, I saw your message and made it. Right now working. Thank you man.

I have a question. Everything works but sometimes VM screen does not come. what could be the reason?
 
I installed second a Proxmox - 4.4.1 and stable working!

But

this time, Proxmox 4.4.1, It does not support the latest versions of operating systems. For example, Ubuntu 17.10

Code:
TASK ERROR: unsupported Ubuntu version '17.10'
 

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!