Skip to content

Instantly share code, notes, and snippets.

@rmpel
Created April 28, 2023 06:26
Show Gist options
  • Save rmpel/37b4d599942596fce3be3153fc5863fb to your computer and use it in GitHub Desktop.
Save rmpel/37b4d599942596fce3be3153fc5863fb to your computer and use it in GitHub Desktop.
A simple proxy in PHP
<?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