Category Archives: Apache 2.2 Windows

Apache and SSL

Yesterday someone remarked: With Apache you cant implement multiple SSL certificates behind one and the same IP address. This remark is actually not quite correct. A good opportunity to explain the basics behind SSL and explain why SSL implementations on servers with multiple sites can be challenging.

Understanding SSL.

SSL is an acronym for ‘Secure Socket Layer’ and is a method to encrypt traffic between client and host. SSL uses a key-pair that is provided by a digital certificate to encrypt the communication. To do this, SSL needs inform the client how to decrypt the traffic prior to the actual communication. This is done by the so called, SSL-handshake, in which a public-key is shared with the client.

Each of the parties (client and host) now have a public and private key available. With this so called keypair both parties are able to encrypt and decrypt the traffic that is being send. Please view the Deffie-Hellman key exchange wikipedia for a clear example of this algorithm.

The Deffie-Hellman example also illustrates the risk of a client losing or sharing its private key.

What is an certificate

In most cases an certificate has multiple purposes. One is obviously to encrypt the traffic. An additional task is to identify the host to the client. The host is usually identified using its public DNS name. By means of the CN (Common Name) field of the certificate, the client is able tot verify that the CN in the certificate is equal to the DNS adres the client is visiting. If either one is not equal, the client will generate an warning.

Why do you still get an warning when you use a valid DNS name in your certificates CN field? Well an additional check is necessary. An external Certificate Authority needs to back your claim. This is done by signing the certificate using an certificates private key that is only known by the Certificate Authority. The client is now able to check (with the public key of that CA) the validity of your certificate and its claim.

You might now understand why there was such a buzz over Diginotar making its private key available to hackers using its auto-signing process.

What is a SOCKET

The second principle to understand is the ‘socket.’ Litteraly a socket is an communication endpoint used by an application to send data. Its important to realize that a socket only contains protocol information (like TCP/UDP or ICMP) and various settings like timeout. Usually IP information isnt given in the socket definition. If a programmer wants the socket to be open on a specific device he usually needs to ‘explicitly bind’ the socket to that IP.

So an socket is nothing more than a ‘door’ to the network that an application can programmatically use to send data over an networked device.

Apache and SSL

In case of Apache httpd SSL is implemented on a listening IP:Port. When a client connects to Apache using the ip:port configured in httpd.conf the first thing that is performed is the SSL handshake. As we noted, the SSL handshake is performed prior to sending actual data. When this is completed, the http request header is send (encrypted) to the Apache instance.

When Apache implements multiple sites behind one socket, called virtual hosts, it uses the ‘http GET header’ to determin the right content (virtual host). Apache can only do this when it received a valid requestheader, that can only be offered after SSL has been implemented.

Now here is the issue.
The http request header we are talking about actually contains a DNS site name, for instance: http://www.google.com. GET /. Now the certificate used also has ‘CN=www.google.com’. In which case there wont be any problem. All checks out, no certificate error.

Now the second site hosted in a different virtual host, provided by the same Apache instance is called using the http request header: logon.google.com. GET /. Now all hell breaks loose because our certificate still contains ‘CN=www.google.com’. The name doesnt match, and a certificate error is risen.

the reason for this is that SSL is actually being implemented by Apache, but prior to the actual request being send. There is no mechanism in place to determine the correct certificate, containing the correct CN prior to the http call.

Possible solutions?

When you are using multiple subdomains behind the same top level domain, for instance: http://www.mysite.com, service.mysite.com, mail.mysite.com. The solution might be to use a so called ‘wildcard’ certificate. This certificates CN name looks like: CN=*.mysite.com and will match correctly against all the subdomains.

When you are using mutiple top level domain sitesnames like: http://www.google.com, http://www.mysite.com, implementing SNI might be a solution. Be warned, SNI has a limited backwards compatibility. The client needs to support SNI to work property.

You could use multiple ports on the server and SSL on the various ports. This will require your visitors to add a port to the url like: https://www.google.com (default 443), https://www.mysite.com:445 (non default).

Alternativly use multiple IPs to bind the ssl. This will enable you to keep the default port 443. Requesting mulitple public IPs to do so might be costly, but is the most elegant solution (next to SNI).

Any questions?
Feel free to post them below 🙂

 

 

 

 

Advertisements

Certificates, what to know…

Certificates is a tough and complex world to be in.

Here are the main things to remember when renewing old certificates, or requesting new ones 🙂

  • CAis a short for “Certificate Authority” and is usually a party that ‘Signs’ certificates on behalf of the requester. Because someone other then the party hosting a site signed the certificate it is assumed that dualism applies.
  • CSR is a short for “Certificate Signing Request” and contains the hash needed by any CA to create a “Signed” certificate.
  • Private Key Is the server keyportion of the certificate that enables the server to “Decrypt” traffic generated by a remote client using the provided certificate. This part of the certificate should always be kept save, and should never be exchanged with any 3rd party. He who has the private key can assume the identity of the server/service on which the certificate applies.
  • Public KeyIs the client keyportion of the certificate that allows a client to decrypt the traffic that is generated by the remote server. This key is exchanged encrypted using the certificate during connection time, and because only the server holds the server portion of the privatekey, he is the only one in the world who can theoretically decode this traffic containing the key.
  • Certificates CN (Common Name) should always comply with the url used by the visiting client. i.e. for google the CN would be http://www.google.com.
  • Certificates O (Organization) should match the company listed in the whois that is performed on the domain name. i.e. for google it would be “Google Inc.” http://www.whois.net/whois/google.com
  • When you want to use the Certificates for Mobile Devices, a special certificate should be used. Check ssl.nu for more information.
  • SAN – is a short for “Subject Alternative Name” not to be mistaken with “Storage Active Network”, it is a special certificate that allows for multiple CNs. (multiple sites) http://www.digicert.com/subject-alternative-name.htm, also used in a number of Microsoft products.
  • If you have an option on this point dont use certificates that use MD5 cryptographic hash . These are considered to be weak, and might be blocked by future browsers being insecure. Weaknesses allow hackers to create a ‘valid’ certificate and steal the identity of you site by applying it. (though read, for the wiz-kids http://www.win.tue.nl/hashclash/rogue-ca/)

This should help you on your way 🙂

this might also be usefull, CSR Checker that will also perform a few checks to make sure all the info inside the CSR adds up.
https://www.networking4all.com/en/support/tools/csr+check/

Simple PHP script to walk and print a directory tree

<?php
function walk_dir($dir){
	$relativedir = '.'.$dir;
	if($dh = opendir($relativedir)){
	while(false !== ($file = readdir($dh))){
		if(($file !== '.') && ($file !== '..')){
			if(!is_dir($relativedir.$file)){
				echo '<a href="'.$dir.$file.'" title="'.$file.'">'.$file.'</a>'."\n";
			}else{
				walk_dir($dir.$file.'/');
			}
		}
	}
	}
}

walk_dir('/');
?>

Templated mail for nagios / centreon.

This command enables you to dynamicly create a nice templated mail.

Save code below into a file inside the /usr/local/nagios/libexec/mailbytpl.php

On linux you can use the vi command to do so; i.e. $>vi /usr/local/nagios/libexec/mailbytpl.php

#!/usr/bin/php

<?php

// Lets define the defaults //
$showman = false;
$tpldata = false;
$debug = false;
$settings['from'] = 'centreon@amis.nl';
$settings['type'] = 'notification';
$settings['host'] = '{hostname?}';
$settings['reply'] = 'NULL';

// Dont change anything below! //
// Find and sort all the commandline arguments //
// Make a distinct difference between known settings and arguments later to be passed into the template //

if(@is_array($argv)){
// Define that the mail setting isnt passed till we realy found it in the argv
$settings['mail'] = false;
foreach($argv as $value){
$keyval = explode("=", $value);
if(array_key_exists('0', $keyval)){
$key = str_replace('--', '', $keyval[0]);
if(array_key_exists('1', $keyval)){
$val = $keyval[1];
}else{
$val = NULL;
}
}
// Default settings we want to fetch //
switch ($key){
case 'mail':
$settings['mail'] = true;
break;
case 'tplfile':
$settings['tplfile'] = $val;
break;
case 'to':
$settings['to'] = $val;
break;
case 'from':
$settings['from'] = $val;
break;
case 'type':
$settings['type'] = $val;
break;
case 'host':
$settings['host'] = $val;
break;
case 'reply':
$settings['reply'] = $val;
case 'verbose':
$debug=true;
break;
default:
                                // Next to the defaults we fetch additional values...
if(!strstr($key, 'mailbytpl.php')){
$arguments[$key] = $val;
}
}
$keyval = '';
$key = '';
$val = '';
}
$arguments['DATE'] = date('Y-m-d H:i:s');
}else{
// If we got no args (default {basename}.ext is allways passed, still need to fix that.//
// Consider this the spaceholder 😉 //
$showman = true;
}
// Validate if all the needed settings where found //
if(!empty($settings['mail']) && !empty($settings['tplfile']) && !empty($settings['to'])){
// Lets try to open the template file//
if($settings['mail']){
if($settings['tplfile']){
//Does the directory exist?//
if(is_dir(dirname($settings['tplfile']))){
if(opendir(dirname($settings['tplfile']))){
if(is_file($settings['tplfile'])){
$tpldata = file($settings['tplfile']);
}else{
die('ERR::Template file doesnt exist or couldnt be opened');
}
}else{
die('ERR::Template file directory coudnt be opened. please verify the rights!');
}
}else{
die('ERR::Template file directory doesnt exist. please verify its existance!');
}
}else{
$showman = true;
}
}else{
$showman = true;
}
// If we have content from the template file, we need to add the information too it //
if($tpldata){
if(count($tpldata) >= 1){
// If we found more then 1 rule we can continue //
// Lets Generate tablerows too place in the template //
$maildata = '';
$cc = '0';
foreach($arguments as $key => $value){
$maildata .= '
<tr>
<td class="datahead'.$cc.'">'.$key.'</td>
<td class="datacontent'.$cc.'">'.$value.'</td>
</tr>
';
$cc++;
}
$maildata .= '<!--Generated by mailbytemplate.php for nagios by AMIS Services BV.-->'."\r\n";
$mailbody ='';
// If there is an element called $DATAROWS$ then insert the pregenerated block//
foreach($tpldata as $lineno => $line){
$pattern = '$DATAROWS$';
$subject = $line;
if(preg_match($pattern, $subject, $matches, PREG_OFFSET_CAPTURE)){
//if there is a match we match it using the arguments//
//Match is found using $matches[0][0]//
$line = str_replace('$DATAROWS$', $maildata, $line);
}
$mailbody .= $line."\r\n";
}
}else{
// We could have loaded an empty file, lets tell the user! //
die('Template file was found to be empty');
}
}
if($mailbody){
                // You can add any header you like...
                $headers ="MIME-Version: 1.0 \r\n";
                $headers.="From: Centreon <".$settings['from'].">\r\n";
                $headers.="Reply-To: ".$settings['reply']." \r\n";
                $headers.="X-Mailer: PHP/".phpversion()."\r\n";
$headers.="Content-type: text/html; charset='us-ascii' \r\n";
$subject =$settings['type'].":: Notification from ".$settings['host']." ...";
mail($settings['to'], $subject, $mailbody, $headers);
}
}else{
$showman = true;
}

if($showman){
// If the mail command isnt found then show the manual //
echo "Using this module is fairly simple, first edit the mainfile mailbytpl.php and alter the defaults \r\n";
echo "Then run the file like the example using the required settings and adding your own using this \r\n";
echo "Format...\r\n";
echo "\r\n\r\n";
echo "{pathtofile}/mailbytpl.php [args]\r\n";
echo "\r\n\r\n";
echo "Valid arguments\r\n";
echo "\t--mail\t\t\t\t\t'Tell the script to execute the mail functionality'\r\n";
echo "\t--tplfile=[path-to-template]\t\t'The path the the template file that should be used by this script'\r\n";
echo "\t--to=[valid@mail.ext]\t\t\t'A valid mailaddress of the receipient,\$CONTACTMAIL$ within nagios\r\n";
echo "\t--from=[valid@mail.ext]\t\t\t'A valid from addres to exclude it from your junkmail folder'\r\n";
echo "\t--reply=[valid@mail.ext]\t\t'Used as reply-to header to redirect mail to different mailboxes. Defaults to 'NULL'\r\n";
echo "\t--type=[NOTIFICATIONTYPE]\t\t'Used in the subject of the mail i.e. [type]::notification for [host]'\r\n";
echo "\t--host=[HOSTNAME]\t\t\t'Used in the subject of the mail i.e. [type]::notification for [host]'\r\n";
echo "\r\n\r\n";
echo "Add your information to the template by adding additional custom entries. using the following syntax;\r\n";
echo "\t--KEY=VALUE\r\n";
echo "\r\n\r\n";
echo "Example for nagios:\r\n";
echo "\$USER1$/mailbytpl --mail --tplfile=\$USER1$\mail.tpl --to=example@mail.nl --from=example@mail.nl --reply=no-reply@mail.nl\r\n";
echo "--type=\$NOTIFICATIONTYPE$ --host=\$HOSTNAME$ --IP=\$HOSTADDRESS$ --DOWNTIME=\$HOSTDOWNTIME$ --YOUROTHERVAR=\$VALUE$ \r\n";
echo "\r\n\r\n\r\nScript by : Chris Gralike\r\nCompany : AMIS Services BV\r\n GPL:2009©\r\n";
}
?>

Next you can configure the command into centreon as a ‘notification’ command that takes the following commands:

–mail                                                         Should be set, enables the mail functionality
–tplfile=[path to template]                  ‘The is the html template that will be used
–to=[valid@email.com]                       Set the receipient
–from=[valid@email.com]                  Set the sender
–reply=[valid@email.com]                  Set the return-path
–type=[NOTIFICATIONTYPE]          used in the subject of the mail.
–host=[HOSTNAME]                           used in the subject of the mail.
–[KEY]=[VALUE]                                  add additional information to the template, these fields are autofilled if used in the template.

example:

$USER1$/mailbytpl --mail --tplfile=\$USER1$\mail.tpl --to=example@mail.nl --from=example@mail.nl --reply=no-reply@mail.nl --type=\$NOTIFICATIONTYPE$ --host=\$HOSTNAME$ --IP=\$HOSTADDRESS$ --DOWNTIME=\$HOSTDOWNTIME$

Next create a template file to point to. I called mine mail.tpl

<html>
<head>
<title>Network notification</title>
<style>
body {background-color:#999; text-align:left; font-family:verdana;}
table{border:1px solid #020245; width:100%;}
th{background-color:#020245; color:#fff; border-bottom:1px solid #020245; text-align:left;}
td{border-bottom:1px solid #020245; background-color:#ccc; font-size:11px;}
tr{height:20px;}
#1{border-style:none; background-color:#ccc;}
.2{width:150px;  font-size:12px; font-weight:bold;}
.3{width:3px;}
</style>
</head>
<body>
<table cellspacing=0 align='center'>
$DATAROWS$</table>
</body>
</html>

Well hope this was usefull for ya 😉

#!/usr/bin/php
<?php
// Lets define the defaults //
$showman = false;
$tpldata = false;
$debug = false;
$settings[‘from’] = ‘centreon@amis.nl’;
$settings[‘type’] = ‘notification’;
$settings[‘host’] = ‘{hostname?}’;
$settings[‘reply’] = ‘NULL’;
// Dont change anything below! //
// Find and sort all the commandline arguments //
// Make a distinct difference between known settings and arguments later to be passed into the template //
if(@is_array($argv)){
        // Define that the mail setting isnt passed till we realy found it in the argv
        $settings[‘mail’] = false;
        foreach($argv as $value){
                $keyval = explode(“=”, $value);
                if(array_key_exists(‘0’, $keyval)){
                        $key = str_replace(‘–‘, ”, $keyval[0]);
                        if(array_key_exists(‘1’, $keyval)){
                                $val = $keyval[1];
                        }else{
                                $val = NULL;
                        }
                }
                // Default settings we want to fetch //
                switch ($key){
                        case ‘mail’:
                                $settings[‘mail’] = true;
                                break;
                        case ‘tplfile’:
                                $settings[‘tplfile’] = $val;
                                break;
                        case ‘to’:
                                $settings[‘to’] = $val;
                                break;
                        case ‘from’:
                                $settings[‘from’] = $val;

PHP : Script to count with barcode reader.

Well these are boring times… I just wrote a script using php to count barcodes with a barcode reader. Though this might be a nice thing to share, maybe someone will find it usefull.

It doesnt use a database, so at some point you`ll need to copy paste the results somewhere. Ow well have fun 😀

 
session_start();

if(isset($_GET['barcode']) || isset($_POST['barcode'])){
 $barcode = (isset($_POST['barcode'])) ? $_POST['barcode'] : $_GET['barcode'];
}else{
 $barcode = false;
}

if($barcode){
 if(@$_SESSION['products'][$barcode]){
  $_SESSION['products'][$barcode] ++;
 }else{
  $_SESSION['products'][$barcode] = 1;
 }
}

if(is_array($_SESSION['products'])){
 foreach($_SESSION['products'] as $barcode =&gt; $count){
  echo " Counted $barcode, $count times allready!<br\>\r\n";
 }
}

Print('
  <html>
  <head>;
  <script type="text/javascript">;
  var formInUse = false;
  function setFocus(){ if(!formInUse) {document.BarForm.barcode.focus();}}
  </script>;
  </head>;
  <body onload="setFocus()">
  <form name="BarForm" action="'.$_SERVER['PHP_SELF'].'" method="GET">;
  <table>
   <tr>
    <td><input type="text" name="barcode" onchange="form.submit()" onfocus="formInUse = true;"></td>
   </tr>
  </table>
  </body>;
  </html>;
');