EAS Secure Proxy (Marke: Eigenbau)

Hallo zusammen,

in Unternehmen sind MDM (Mobile Device Management) Systeme bereits sehr etabliert. Diese können nicht nur das Smartphone verwalten, sondern sie reglementieren auch den Zugriff auf den Exchange via ActiveSync/PushMail. Dieser Zugriff wird meist mit einem Reverse-Proxy realisiert, ein sogenannter EAS-Proxy (Exchange Active Sync Proxy).

Um auch diese Sicherheit auch privat nutzen zu können, habe ich mir ein kleines PHP-Skript geschrieben, welches die Aufgabe eines EAS-Proxy für mich übernimmt – getauft von mir als EAS Secure Proxy.

Die Realisierung ist dabei recht simple:
– Ich reiche alle Anfragen vom Smartphone direkt auf den Mailserver via ActiveSync durch
– Sofern verfügbar, prüfe ich jedoch den Request auf „Benutzername“ und verwendete „Device ID“

Als Beispiel für einen solchen Aufruf:

https://mailserver.domain.tld/Microsoft-Server-ActiveSync?User=hanswurst&DeviceId=GERAETEIDBIWNIEWCNI&DeviceType=HERSTELLER&Cmd=Ping

Nachfolgend mein Skript für die Realisierung. Es fehlt momentan noch eine Anbindung an eine Datenbank für die Protokollierung, sowie aber auch Benutzer und DeviceID möchte ich dort pflegen.
Das Skript kann einfach als Alias für „/Microsoft-Server-ActiveSync“ in einem Apache eingebunden werden. Beispiel für die Einbindung in der httpd.conf:

Alias /Microsoft-Server-ActiveSync /var/www/html/php_scripte/eassp.php

 

Und nun das eigentliche PHP-Skript:

<?php
$loglevel_array = array("INFO", "WARNING", "DEBUG");
define("LOGLEVEL_INFO", 0);
define("LOGLEVEL_WARNING", 1);
define("LOGLEVEL_DEBUG", 2);
// -------------------------------------------------------------------------------------------
//                                     EAS-Secure Proxy
// -------------------------------------------------------------------------------------------
//
// $eas_server
// Definiert den Exchange ActiveSync Server
$eas_server = "http://mailserver.domain.tld/";
//
// $loglevel
// Definiert das Loglevel, Optionen sind:
// LOGLEVEL_INFO       -- Nur Informationen
// LOGLEVEL_WARNING    -- Informationen und Warnungen
// LOGLEVEL_DEBUG      -- Debug Nachrichten
$loglevel = LOGLEVEL_INFO;
//
// -------------------------------------------------------------------------------------------
openlog("EASSP", LOG_PID | LOG_NDELAY, LOG_USER);
function logme($myLevel, $myMsg) 
{
   global $loglevel, $loglevel_array;
   if($myLevel <= $loglevel)
   {
      syslog(LOG_NOTICE, $loglevel_array[$loglevel] . " - " . $myMsg);
   }
}

// Global Settings
$script_max_time = ini_get('max_execution_time');
logme(LOGLEVEL_WARNING, "MAX_EXECUTION_TIME = " . $script_max_time . " [loaded from php.ini]");

// Check Authentication
if($_SERVER["REQUEST_METHOD"]=="GET" OR ($_SERVER["REQUEST_METHOD"]=="POST" AND (!isset($_GET["User"]) OR !isset($_GET["DeviceId"]) OR !isset($_GET["DeviceType"]))))
{
   // Confuse Client and Send Auth-Req
   logme(LOGLEVEL_INFO, "ATTENTION! Unauthenticated Request from " . $_SERVER["REMOTE_ADDR"] . " / " . $_GET["User"]);
   http_response_code(401);
   header("WWW-Authenticate: Basic realm='noExchange'");
   die();
}
if($_SERVER["REQUEST_METHOD"]=="POST")
{
   if(strtoupper($_GET["User"])!="HANSUWRST" OR strtoupper($_GET["DeviceId"])!="MEINEGERAETEIDBLABLA")
   {
      logme(LOGLEVEL_INFO, "ATTENTION! Unauthenticated Request from " . $_SERVER["REMOTE_ADDR"] . " / " . $_GET["User"] . " / " . $_GET["DeviceId"]);
      http_response_code(404);
      die();
   }
}
logme(LOGLEVEL_INFO, "---------------------- [STARTING REQUEST] ----------------------");
logme(LOGLEVEL_INFO, "Authentication for [" . $_GET["User"] . "] succeeded from [" . $_SERVER["REMOTE_ADDR"] . "]");

// Build complete EAS URL
$eas_url = $eas_server . $_SERVER["REQUEST_URI"];
logme(LOGLEVEL_INFO, "COMPLETE EAS-URL = " . $eas_url);

// Check cURL    
if (!function_exists('curl_init'))
{
    logme(LOGLEVEL_INFO, "ERROR/EXIT; Sorry cURL is not installed!");
    die("Sorry cURL is not installed!");
} else {
    logme(LOGLEVEL_WARNING, "Found Module cURL [existing function curl_init]");
}

// Build cURL Instance
$ch = curl_init();

// Load POST RAW Data
$postRawData = "";
$inp = fopen("php://input", "r");
while(!feof($inp)) {
    $buffer = fread($inp, 8192);
    $postRawData.=$buffer;
}
logme(LOGLEVEL_DEBUG, "RAW POST DATA = " . $postRawData);

// Set cURL Options
// Check if Request is POST/OPTIONS
logme(LOGLEVEL_DEBUG, "REQUEST METHOD = " . $_SERVER["REQUEST_METHOD"]);
if($_SERVER["REQUEST_METHOD"]!="GET") {
    logme(LOGLEVEL_DEBUG, "Preparing REQUEST as POST");
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postRawData);
}

// Build Header from Request
$tmpHeader = array();
foreach(getallheaders() as $name => $value) {
   logme(LOGLEVEL_DEBUG, "REQUEST HEADER [" . $name . ": " . $value . "]");
   if($name!="Authorization") array_push($tmpHeader, $name . ": " . $value);
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $tmpHeader);

// Global cURL Options
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $_SERVER["REQUEST_METHOD"]);
logme(LOGLEVEL_DEBUG, "REQUEST USER = " . $_SERVER['PHP_AUTH_USER']);
curl_setopt($ch, CURLOPT_USERPWD, $_SERVER['PHP_AUTH_USER'] . ":" . $_SERVER['PHP_AUTH_PW']);
curl_setopt($ch, CURLOPT_URL, $eas_url);
logme(LOGLEVEL_DEBUG, "REQUEST USERAGENT = " . $_SERVER['HTTP_USER_AGENT']);
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
logme(LOGLEVEL_DEBUG, "REQUEST TIMEOUT = " . $script_max_time);
curl_setopt($ch, CURLOPT_TIMEOUT, $script_max_time);

// Process Request to EAS
$eas_result = curl_exec($ch);

// Get Response Header
$eas_response_header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$eas_response_header = substr($eas_result, 0, $eas_response_header_size);

// Get Response Body
$eas_response_body = substr($eas_result, $eas_response_header_size);

// Close Filehandler
curl_close($ch);

// Set Response Header for Script
$eas_response_header_array = explode("\n", $eas_response_header);
for($i=0; $i<count($eas_response_header_array); $i++)
{
    logme(LOGLEVEL_WARNING, "RESPONSE HEADER : " . $eas_response_header_array[$i]);
    header($eas_response_header_array[$i]);
}

// Return Response Body for Script
print($eas_response_body);
logme(LOGLEVEL_INFO, "---------------------- [REQUEST FINISHED] ----------------------");
closelog();
?>

Da ich eher funktional Skripte schreibe, habe ich mal auf Objektorientierung verzichtet ;-)

 

Grüße

Empfohlene Beiträge

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Schaltfläche "Zurück zum Anfang"