Created
April 28, 2023 06:26
-
-
Save rmpel/37b4d599942596fce3be3153fc5863fb to your computer and use it in GitHub Desktop.
A simple proxy in PHP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @file proxy.php Proxy requests to a different server. Very useful for example to set-up Let's Encrypt on a new server without the domain resolving to it. | |
* | |
* Step 1: set-up a domain pointer on the target server that DOES resolve to the same webspace as the original domain. | |
* Step 2: place code in the .htaccess in the source server as well as this php file. | |
* Step 3: configure the $target_domain to point to your newly set-up domain pointer. | |
* | |
* Final note: the 'verbose' function is for debugging this code only. It will probably be of no use to you. | |
*/ | |
/** | |
* USE THIS HTACCESS: | |
* In this example, we proxy only Let's Encrypt (or other ACME SSL providers) validation requests. | |
* You will need to configure what to proxy yourself. | |
*/ | |
$htaccess = <<< EOHTA | |
RewriteEngine On | |
RewriteRule ^.well-known proxy.php [L,NC,QSA] | |
EOHTA; | |
/** | |
* Set-up target domain pointer | |
*/ | |
$target_domain = "this-is-my.domainpointer.to.mynewserver.com"; | |
$current_request = $_SERVER['REQUEST_URI']; | |
$current_method = $_SERVER['REQUEST_METHOD']; | |
curl_request($current_method, "http://$target_domain/" . ltrim($current_request, '/'), $_POST, false, $_SERVER['HTTP_REFERER'], false, true, array(), 120, $_SERVER['HTTP_USER_AGENT']); | |
function curl_request( | |
$method = 'GET', | |
$url, | |
$data = array(), | |
$verbose = false, | |
$ref_url = false, | |
$cookie_location = false, | |
$return_transfer = true, | |
$headers = array(), | |
$timeout = 1, | |
$user_agent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.28 Safari/534.10", | |
$verify_ssl = false, | |
$return_instead_of_execute = false | |
) { | |
$return_val = false; | |
$pointer = curl_init(); | |
if ($verbose) { | |
curl_setopt( $pointer, CURLOPT_VERBOSE, true); | |
header("Content-Type: text/plain"); | |
$verbose_file = __DIR__ .'/log.txt'; | |
} | |
if ($verbose) print "Setting CURLOPT_URL to ". json_encode( $url ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_URL, $url ); | |
if ($verbose) print "Setting CURLOPT_TIMEOUT to ". json_encode( max( 1, intval( $timeout ) ) ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_TIMEOUT, max( 1, intval( $timeout ) ) ); | |
if ($verbose) print "Setting CURLOPT_RETURNTRANSFER to ". json_encode( $return_transfer ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_RETURNTRANSFER, $return_transfer ); | |
if ($verbose) print "Setting CURLOPT_USERAGENT to ". json_encode( $user_agent ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_USERAGENT, $user_agent ); | |
if ($verbose) print "Setting CURLOPT_SSL_VERIFYHOST to ". json_encode( $verify_ssl ? 2 : 0) ."\n"; | |
curl_setopt( $pointer, CURLOPT_SSL_VERIFYHOST, $verify_ssl ? 2 : 0); | |
if ($verbose) print "Setting CURLOPT_SSL_VERIFYPEER to ". json_encode( $verify_ssl ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_SSL_VERIFYPEER, $verify_ssl ); | |
if ($verbose) print "Setting CURLOPT_HEADER to ". json_encode( true ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_HEADER, true ); | |
if ($verbose) print "Setting CURLOPT_FOLLOWLOCATION to ". json_encode( true ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_FOLLOWLOCATION, true ); | |
if ($verbose) print "Setting CURLOPT_AUTOREFERER to ". json_encode( true ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_AUTOREFERER, true ); | |
if ( $cookie_location !== false ) { | |
if ($verbose) print "Setting CURLOPT_COOKIEJAR to ". json_encode( $cookie_location ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_COOKIEJAR, $cookie_location ); | |
if ($verbose) print "Setting CURLOPT_COOKIEFILE to ". json_encode( $cookie_location ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_COOKIEFILE, $cookie_location ); | |
if ($verbose) print "Setting CURLOPT_COOKIE to ". json_encode( session_name() . '=' . session_id() ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_COOKIE, session_name() . '=' . session_id() ); | |
} | |
if ( $verbose_file !== false ) { | |
$verbose_file_pointer = fopen( $verbose_file, 'w' ); | |
if ($verbose) print "Setting CURLOPT_VERBOSE to ". json_encode( true ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_VERBOSE, true ); | |
if ($verbose) print "Setting CURLOPT_STDERR to ". json_encode( $verbose_file_pointer ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_STDERR, $verbose_file_pointer ); | |
} | |
if ( $ref_url !== false ) { | |
if ($verbose) print "Setting CURLOPT_REFERER to ". json_encode( $ref_url ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_REFERER, $ref_url ); | |
} | |
if ( is_array( $data ) ) { | |
if ( count( $data ) == 0 ) { | |
$data = false; | |
} | |
} else { | |
if ( ! trim( $data ) ) { | |
$data = false; | |
} | |
} | |
if ( $data && $method == 'POST' ) { | |
if ($verbose) print "Setting CURLOPT_POST to ". json_encode( true ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_POST, true ); | |
if ($verbose) print "Setting CURLOPT_POSTFIELDS to ". json_encode( $data ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_POSTFIELDS, $data ); | |
} | |
if ( $data && $method == 'GET' ) { | |
$data = is_array($data) ? http_build_query($data) : $data; | |
$url = $url . (false !== strpos($url, '?') ? '&' : '?'). $data; | |
} | |
$headers['X-Forwarded-For'] = $_SERVER['REMOTE_ADDR']; | |
if ( count( $headers ) ) { | |
$ua = null; | |
foreach ( $headers as $key => $value ) { | |
if ( strtolower( $key ) == 'user-agent' || false !== strpos( strtolower( $value ), 'user-agent:' ) ) { | |
$ua = is_numeric( $key ) ? trim( @end( explode( ':', $value, 2 ) ) ) : trim( $value ); | |
unset( $headers[ $key ] ); | |
} | |
if ( is_numeric( $key ) && false !== strpos( $value, ':' ) ) { | |
$headers[ $key ] = $value; // :P | |
} else { | |
$headers[ $key ] = $key . ": " . $value; | |
} | |
} | |
// if user agent in headers, overrule user agent. | |
if ( $ua ) { | |
if ($verbose) print "Setting CURLOPT_USERAGENT to ". json_encode( $ua ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_USERAGENT, $ua ); | |
} | |
if ($verbose) print "Setting CURLOPT_HTTPHEADER to ". json_encode( $headers ) ."\n"; | |
curl_setopt( $pointer, CURLOPT_HTTPHEADER, $headers ); | |
} | |
$return_val = curl_exec( $pointer ); | |
$header_size = curl_getinfo($pointer, CURLINFO_HEADER_SIZE); | |
$return_header = substr($return_val, 0, $header_size); | |
$return_val = substr($return_val, $header_size); | |
$http_code = curl_getinfo( $pointer, CURLINFO_HTTP_CODE ); | |
if ($return_instead_of_execute) { | |
if ( $http_code == 404 ) { | |
return false; | |
} | |
if ( $http_code == 204 ) { | |
return ''; | |
} | |
curl_close( $pointer ); | |
unset( $pointer ); | |
return $return_val; | |
} | |
else { | |
ob_start('ob_gzhandler'); | |
array_map('maybe_header', explode("\n", $return_header)); | |
http_response_code($http_code); | |
print $return_val; | |
} | |
} | |
function maybe_header($header) { | |
if (false !== strpos(strtolower($header), 'content-length')) { | |
return; | |
} | |
header($header); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment