Skip to content

Instantly share code, notes, and snippets.

@Daij-Djan
Last active August 16, 2021 09:27
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Daij-Djan/9031974 to your computer and use it in GitHub Desktop.
Save Daij-Djan/9031974 to your computer and use it in GitHub Desktop.
Proxy for ANY POST http request. The script can handle POST data, a custom content type, SSL, user/password credentials and 401 errors from the target.
<?php
//
// executeRequest
//
// uses cURL to run a http(s) request.
// data, contentType, user, password are all optional
//
function executeRequest($target, $data, $contentType, $user, $password, &$http_status) {
//try to send request to remote
$i = 0;
$max_tries = 3;
$output = null;
do {
//log retries
if($i > 0) {
syslog(LOG_NOTICE, "Last try timed out. Retrying Request to " . $target);
}
//setup curl with url
$ch = curl_init($target);
//set options
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30); //timeout in seconds
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT ,10);
//forward content type header
if($contentType) {
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: $contentType" ));
}
//POST data
if($data!=false) {
curl_setopt($ch, CURLOPT_POST, true );
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
//user auth
if($user && $password) {
curl_setopt($ch, CURLOPT_USERPWD, $user.':'.$password);
}
//GO!
$output = curl_exec($ch);
$http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curl_errno = curl_errno($ch);
$curl_error = curl_error($ch);
$curl_info = curl_getinfo($ch);
if ($curl_errno == 0) {
break;
}
curl_close($ch);
//on error, repeat
syslog(LOG_NOTICE, "cURL Error ($curl_errno): $curl_error");
$i++;
} while($i < $max_tries);
return $output;
}
?>
<?php
include('executeRequest.inc.php');
//get server data
$target = (isset($_GET["TARGET"]) ? $_GET["TARGET"] : '');
if(!$target) {
die("the proxy needs a target");
}
$data = file_get_contents('php://input');
$contentType = (isset($_SERVER["CONTENT_TYPE"]) ? $_SERVER["CONTENT_TYPE"] : '');
$user = (isset($_SERVER["PHP_AUTH_USER"]) ? $_SERVER["PHP_AUTH_USER"] : '');
$password = (isset($_SERVER["PHP_AUTH_PW"]) ? $_SERVER["PHP_AUTH_PW"] : '');
//it is a specialized for windows here
$domain = (isset($_GET["DOMAIN"]) ? $_GET["DOMAIN"] : '');
if($domain) {
$user = $domain . '\\' . $user;
}
//queryify if needed
$parts = explode("?", $target);
$query = "";
if(count($parts) == 2) {
$query = "?" . urlencode($parts[1]);
}
foreach ($_GET as $key => $value) {
if($key != "TARGET" && $key != "DOMAIN") {
$param = $query == "" ? "?" : "&";
$query .= $param . urlencode($key . "=" . $value);
}
}
if($query != "") {
$target = $parts[0] . $query;
}
//log
syslog(LOG_DEBUG, "Proxy call to " . $target);
if($data) syslog(LOG_DEBUG, "call has data " + $data);
if($contentType) syslog(LOG_DEBUG, "call has contentType " + $contentType);
if($user) syslog(LOG_DEBUG, "call has user " + $user);
if($password) syslog(LOG_DEBUG, "call has password ***");
//run
$http_status = 0;
$output = executeRequest($target, $data, $contentType, $user, $password, $http_status);
// we always sent the required type
header("Content-Type: $contentType");
//get hostname
$target_host = parse_url($target, PHP_URL_HOST);
//if we failed give a password, quit
if($http_status == 401) {
header('WWW-Authenticate: Basic realm="'.$target_host.'"');
header('HTTP/1.0 401 Unauthorized');
echo "Can't access . $target_host";
exit;
}
//return output
if(strlen($output)) {
echo $output;
}
else {
echo "no data from " . $target_host;
}
?>
@Daij-Djan
Copy link
Author

added handling of query parameters

@N-X-T
Copy link

N-X-T commented Mar 10, 2021

hello, how to use this script, i need guide. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment