Proxy and accessing https://<domain>:10000

Due to work configuration on the proxy. I cannot access my domains control panel on https://

How would I go about setting up a proxy on my server that will let me load it still?
I plan to lock down the proxy with .htaccess etc.

Actually thinking on this, there was a cPanel script to allow this for cPanel servers.
You’d just go to cpanel. and it would do it all automatically.

How can I do this with virtualmin?

bump

anyone?

Actually. Using my meager understanding thought I might look at how to do this.
I have a subdomain setup I’m not using atm so just ninja’d the pre-existing subdomain.

As a result here’s the (slightly) modified code.

<?php
/* cPanel Proxy 0.4.1
 * http://cpanelproxy.net/
 *
 * See README.txt
 *
 */

//// Config

$version = '0.4.1'; // Please don't change this one. :)

// Last part of hostnames (see install instructions)
// Autodetect by removing first element of current hostname
$hostpostfix = preg_replace('/^.*?\./', '', $_SERVER['HTTP_HOST']);

// First parts of hostnames
$webmailhost = 'webmail.'.$hostpostfix;
$cpanelhost = 'cpanel.'.$hostpostfix;
$whmhost = 'whm.'.$hostpostfix;

// If server is running in CGI-mode HTTP Authentification won't work. If 
// $cgimode is "true", cPanel Proxy will hide HTTP Authentification, forcing 
// cPanel to fall back on Cookie Authentification.
// This means that cPanel Proxy is no longer transparent to the user, as the 
// login-screen will look different than usual.
// Defaults to "true" as it will always works, autodetection may be added 
// later.
$cgimode = true;

// The host where cPanel is running. I strongly suggest having this script on 
// the same server as cPanel, and leaving this setting at default "localhost".
$host = 'localhost';

// I'm honestly not sure if \r\n or \n is most correct, but in this case it 
// just needs to work.
$nl = "\r\n";

//// End of config

if ($_SERVER["QUERY_STRING"]=='cPanelProxyVersion') {
  echo '<p><a href="http://cpanelproxy.net/">cPanel Proxy</a> '
    .$version.'</p>';
  exit;
}

function error($header, $string) {
  echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>Error</title>
</head>
<body>
<h1>Error: '.$header.'</h1>
'.$string.'
<hr />
<div style="font-size: 0.8em;"><a href="http://cpanelproxy.net/">'
.'cPanel Proxy '.$version.'</a></div>
</body>
</html>
';
}

switch($_SERVER['HTTP_HOST']) {
 case $webmailhost:
   $port = 20000;
   break;
 case $cpanelhost:
   $port = 10000;
   break;
 case $whmhost:
   $port = 2086;
   break;
 default:
   error(
	 'Hostname not recognized','<p>Server is misconfigured or you have '
.'entered a wrong address. You can try these in stead:</p>

<table>
<tr><td>Webmail: </td><td><a href="http://'.$webmailhost.'/">http://'
.$webmailhost.'/</a></td></tr>
<tr><td>cPanel: </td><td><a href="http://'.$cpanelhost.'/">http://'
.$cpanelhost.'/</a></td></tr>
<tr><td>WHM: </td><td><a href="http://'.$whmhost.'/">http://'.$whmhost
.'/</a></td></tr>
</table>
');
   exit;
}


//// Get headers from browser

// "/webmail" is replaced with "/webmail_" in the url, so the server won't
// redirect browsers using this proxy for webmail.
// The protocol is hardcoded to HTTP 1.0. Then we don't have to worry about
// chunked transfers, as 1.1 forces you to.
$frombrowser = $_SERVER['REQUEST_METHOD']." "
.str_replace('/webmail_', '/webmail',$_SERVER['REQUEST_URI'])." "
.'HTTP/1.0'.$nl;


foreach($_SERVER as $a=>$b) {
  if ($a == 'HTTP_HOST') $b = "$host:$port";
  if ($a == 'HTTP_CONNECTION') $b = "Close"; // FIXME: Maybe a persitent socket could be good for performance. Do we need to make sure only the same browser reuses a socket, or is persistent sockets as stateless as usual?
  if (substr($a,0,5)=='HTTP_') {
    $frombrowser .= substr($a,5)
      .': '. $b.$nl;
  }
}

// That was the regular headers. Now we need to re-generate the headers that 
// was parsed and thrown away before this script gets a chance to see them.

// First authentication.
if (isset($_SERVER['PHP_AUTH_USER']) 
    && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
  $frombrowser .= "Authorization: Basic "
.base64_encode($_SERVER['PHP_AUTH_USER'].':'.$_SERVER['PHP_AUTH_PW']).$nl;
}

if (strlen(@$_SERVER['CONTENT_TYPE'])) {
  $frombrowser .= "Content-Type: ".$_SERVER['CONTENT_TYPE'].$nl;
}
 
// End of browsers headers (for now).

switch($_SERVER['REQUEST_METHOD']) {

 case 'HEAD':
 case 'GET':
   // We're done, signalling this with an extra newline.
   $frombrowser .= $nl;
   break;

 case 'POST':
   // We probably have a body, we need to include this.
   
   $input = fopen('php://input','r');
   $frombrowser_body = '';

   if (strpos(@$_SERVER['CONTENT_TYPE'], 'multipart/form-data')===false) {

     // Not multipart/form-data, sending body directly from browser
     
     // First we get the entire post body.
     while (true) {
       $data = fread($input, 10240); // FIXME: Can we optimize here with another buffer-size?
       if (strlen($data)===0) break;
       $frombrowser_body .= $data;
     }
   } else {

     // multipart/form-data
     
     $boundary = '--------'.md5(time()); // FIXME: Do we need a better algorithm to generate boundary string?
     $frombrowser .= "Content-Type: multipart/form-data; boundary="
       .$boundary.$nl;
     foreach($_POST as $name=>$data) {
       $frombrowser_body .= '--'.$boundary.$nl
	 .'Content-Disposition: form-data; name="'.$name.'"'.$nl
	 .$nl.$data.$nl; // FIXME: If $data is an array, handle that correctly.
     }

     foreach($_FILES as $name=>$data) {
       if (!is_uploaded_file($data['tmp_name'])) continue;

       $frombrowser_body .= '--'.$boundary.$nl
	 .'Content-Disposition: form-data; name="'.$name.'";'
	 .' filename="'.$data['name'].'"'.$nl; // FIXME: Do we need some kind of encoding here? What if the filename (or the name) has characters like double-quote, colon, semicolon, \n or \r?
       // (Uploading a file with double-quote in filename with Mozilla thru this script fails, I have not done any further testing yet.)
       $frombrowser_body .= 'Content-Type: '.$data['type'].$nl
	 .$nl
	 .file_get_contents($data['tmp_name'])
	 .$nl;
     }
     $frombrowser_body .= '--'.$boundary.$nl;
    }
   
   // Okay, now we can finish the headers and attach the body.
   $frombrowser .= "Content-Length: ".strlen($frombrowser_body).$nl
     .$nl
     .$frombrowser_body;

   break;

 default:
   error(
	 'Method not implemented',
	 '<p>Method '.$_SERVER['REQUEST_METHOD'].' not supported in cPanel '
.'Proxy, sorry.</p>'
	 );
   exit;
}

// Time to contact server and send request
$server = fsockopen($host, $port);
fputs($server, $frombrowser);


// Get server headers

if ($cgimode) {
  $firstline = fgets($server, 10240);
  $array = explode(' ', $firstline);
  $status = (int)$array[1];
  if ($status==401) {
    // Authentication needed, but HTTP authentication doesn't work in CGI-mode.
    header('Status: 200');
  } else {
    header($firstline);
  }

}


while (true) {
  $data = fgets($server, 10240); // FIXME: Can we optimize here with another buffer-size?
  if (strlen(trim($data))==0) break;

  // Fix hostname in redirects, cookies...
  $data = str_replace(
	      array('localhost:20000', 'localhost:10000', 'localhost:2086'),
	      array($webmailhost,      $cpanelhost,     $whmhost),
	      $data);
  if (substr($data, 0, 11) == 'Set-Cookie:') {
    $data = str_replace(
			'; domain=localhost', 
			'; domain='.$_SERVER['HTTP_HOST'], 
			$data);
  }

  header($data, false);
}

if($_SERVER['REQUEST_METHOD']=='HEAD') {
  exit;
}

// Get server body
$data = '';
while (true) {
  $line = fgets($server, 10240); // FIXME: Can we optimize here with another buffer-size?

  if (strlen($line)===0) break;
  // A line will never be completely empty, as it will end with a "newline". 
  // So if we get a completely empty line, there's no more data.

  if ($cgimode) {
    // Let's hide that ugly message. It's not the browser that doesn't support 
    // HTTP-Auth, it's CGI...
    $line = str_replace('If your browser does not support HTTP '
			.'Authentication, please use this form:','',$line);
  }

  // Fix hostname 
  $line = str_replace(
	      array('localhost:20000', 'localhost:10000', 'localhost:2086'),
	      array($webmailhost,      $cpanelhost,     $whmhost),
	      $line);

  $data .= preg_replace('_(\'|"|=)/webmail_', '$1/webmail_', $line);
  // This has heavy influence on chunk-size (for HTTP/1.1 to browser)
  if (strlen($data)>10240) { // FIXME: Can we optimize here with another buffer-size?
    echo $data;
    flush();
    $data = '';
  }
}
// $data is probably not empty.
echo $data;
?>

Problem is it’s still calling “http://:10000/” somewhere and I can’t quite make sense on how to make it work on https://:10000/

Pointers?

EDIT:

I am aware that the cpanel proxy prob won’t even work for this out of the box… but. The fact I get a message saying “server is running in SSL Secure mode” when I access “https://hosting./” means… it is working to a degree.

Howdy,

You should also be able to setup a proxy within Virtualmin to do that… if you go into Server Configuration -> Edit Proxy Website, you should be able to proxy that particular Virtual Server to forward to Virtualmin.

That is, if you setup a Virtual Server named vm.example.com, and tell it to proxy connections to https://your_domain.com:10000, that should do what you’re after.

-Eric

Hurm - that seems more simple… :slight_smile:

I’ll have to do that tonight (can’t get into SSL at work >.< )

Hurm - just did the change via my mobile and accessed it.

I get this

Error - No cookies

Your browser does not support cookies, which are required for this web server to work in session authentication mode

edit:
ahh - redid as https:// and it worked.

AWESOME! thanks :slight_smile:

I now get this when i try to go and edit the proxy config settings for another domain.

[code]
Security Warning
Warning! Webmin has detected that the program https://:10000/virtual-server/proxy_form.cgi?dom=125887368685941& was linked to from the URL https://webmin./left.cgi?mode=virtualmin&dom=125887368685941, which appears to be outside the Webmin server. This may be an attempt to trick your server into executing a dangerous command.

If this is a legitimate link, you can allow links from this URL as follows :

* Login to Webmin normally.
* Go to the Webmin Configuration module.
* Click on the Trusted Referrers icon.
* Enter the hostname <domain> into the Trusted websites field, and click Save.

Alternately, you can configure Webmin to allow this link from the command line by :

* Login as root, and edit the /etc/webmin/config file.
* Add the line referers=<domain> at the end, or if a referers line already exists add <domain> to it.
* Save the file.[/code]

I have done as above and restarted httpd / webmin and still get the same message…

Hurm - I edited the /config file and set referrers=1 and now it works.

Strange.

Here’s what I did:

  • Created a sub domain webmin.mydomain.com (for example)
  • In Server Configuration -> Edit Proxy Website set Proxying Enabled to Yes and write the Proxy to URL https://mydomain.com:10000
  • Select mydomain.com in Virtualmin and in Server Configuration -> Manage SSL Certificate -> Let’s Encrypt -> Request certificate (if you don’t have already a certificate for this domain)
  • In Server Configuration -> Manage SSL Certificate click the Copy to Webmin button to use mydomain.com certificate for webmin
  • In Webmin, Webmin -> Webmin Configuration -> Trusted referrers add mydomain.com and webmin.mydomain.com to the Trusted websites list

Now https://webmin.mydomain.com can be accessed even behind the most annoying firewalls!