zoukankan      html  css  js  c++  java
  • PHP Proxy 负载均衡技术

    <?php
    $whitelistPatterns = array(
    );
    $forceCORS = false;
    $anonymize = true;
    $startURL = "";
    $landingExampleURL = "https://example.net";
    /****************************** END CONFIGURATION ******************************/
    ob_start("ob_gzhandler");
    if (version_compare(PHP_VERSION, "5.4.7", "<")) {
      die("miniProxy requires PHP version 5.4.7 or later.");
    }
    $requiredExtensions = ["curl", "mbstring", "xml"];
    foreach($requiredExtensions as $requiredExtension) {
      if (!extension_loaded($requiredExtension)) {
        die("miniProxy requires PHP's "" . $requiredExtension . "" extension. Please install/enable it on your server and try again.");
      }
    }
    
    function getHostnamePattern($hostname) {
      $escapedHostname = str_replace(".", ".", $hostname);
      return "@^https?://([a-z0-9-]+.)*" . $escapedHostname . "@i";
    }
    //Helper function used to removes/unset keys from an associative array using case insensitive matching
    function removeKeys(&$assoc, $keys2remove) {
      $keys = array_keys($assoc);
      $map = array();
      $removedKeys = array();
      foreach ($keys as $key) {
        $map[strtolower($key)] = $key;
      }
      foreach ($keys2remove as $key) {
        $key = strtolower($key);
        if (isset($map[$key])) {
          unset($assoc[$map[$key]]);
          $removedKeys[] = $map[$key];
        }
      }
      return $removedKeys;
    }
    if (!function_exists("getallheaders")) {
      //Adapted from http://www.php.net/manual/en/function.getallheaders.php#99814
      function getallheaders() {
        $result = array();
        foreach($_SERVER as $key => $value) {
          if (substr($key, 0, 5) == "HTTP_") {
            $key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5)))));
            $result[$key] = $value;
          }
        }
        return $result;
      }
    }
    $usingDefaultPort =  (!isset($_SERVER["HTTPS"]) && $_SERVER["SERVER_PORT"] === 80) || (isset($_SERVER["HTTPS"]) && $_SERVER["SERVER_PORT"] === 443);
    $prefixPort = $usingDefaultPort ? "" : ":" . $_SERVER["SERVER_PORT"];
    //Use HTTP_HOST to support client-configured DNS (instead of SERVER_NAME), but remove the port if one is present
    $prefixHost = $_SERVER["HTTP_HOST"];
    $prefixHost = strpos($prefixHost, ":") ? implode(":", explode(":", $_SERVER["HTTP_HOST"], -1)) : $prefixHost;
    define("PROXY_PREFIX", "http" . (isset($_SERVER["HTTPS"]) ? "s" : "") . "://" . $prefixHost . $prefixPort . $_SERVER["SCRIPT_NAME"] . "?");
    //Makes an HTTP request via cURL, using request data that was passed directly to this script.
    function makeRequest($url) {
      global $anonymize;
      //Tell cURL to make the request using the brower's user-agent if there is one, or a fallback user-agent otherwise.
      $user_agent = $_SERVER["HTTP_USER_AGENT"];
      if (empty($user_agent)) {
        $user_agent = "Mozilla/5.0 (compatible; miniProxy)";
      }
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
      //Get ready to proxy the browser's request headers...
      $browserRequestHeaders = getallheaders();
      //...but let cURL set some headers on its own.
      $removedHeaders = removeKeys($browserRequestHeaders, array(
        "Accept-Encoding", //Throw away the browser's Accept-Encoding header if any and let cURL make the request using gzip if possible.
        "Content-Length",
        "Host",
        "Origin"
      ));
      $removedHeaders = array_map("strtolower", $removedHeaders);
      curl_setopt($ch, CURLOPT_ENCODING, "");
      //Transform the associative array from getallheaders() into an
      //indexed array of header strings to be passed to cURL.
      $curlRequestHeaders = array();
      foreach ($browserRequestHeaders as $name => $value) {
        $curlRequestHeaders[] = $name . ": " . $value;
      }
      if (!$anonymize) {
        $curlRequestHeaders[] = "X-Forwarded-For: " . $_SERVER["REMOTE_ADDR"];
      }
      //Any `origin` header sent by the browser will refer to the proxy itself.
      //If an `origin` header is present in the request, rewrite it to point to the correct origin.
      if (in_array("origin", $removedHeaders)) {
        $urlParts = parse_url($url);
        $port = $urlParts["port"];
        $curlRequestHeaders[] = "Origin: " . $urlParts["scheme"] . "://" . $urlParts["host"] . (empty($port) ? "" : ":" . $port);
      };
      curl_setopt($ch, CURLOPT_HTTPHEADER, $curlRequestHeaders);
      //Proxy any received GET/POST/PUT data.
      switch ($_SERVER["REQUEST_METHOD"]) {
        case "POST":
          curl_setopt($ch, CURLOPT_POST, true);
          $postData = Array();
          parse_str(file_get_contents("php://input"), $postData);
          if (isset($postData["miniProxyFormAction"])) {
            unset($postData["miniProxyFormAction"]);
          }
          curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
        break;
        case "PUT":
          curl_setopt($ch, CURLOPT_PUT, true);
          curl_setopt($ch, CURLOPT_INFILE, fopen("php://input", "r"));
        break;
      }
      //Other cURL options.
      curl_setopt($ch, CURLOPT_HEADER, true);
      curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      //Set the request URL.
      curl_setopt($ch, CURLOPT_URL, $url);
      //Make the request.
      $response = curl_exec($ch);
      $responseInfo = curl_getinfo($ch);
      $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
      curl_close($ch);
      //Setting CURLOPT_HEADER to true above forces the response headers and body
      //to be output together--separate them.
      $responseHeaders = substr($response, 0, $headerSize);
      $responseBody = substr($response, $headerSize);
      return array("headers" => $responseHeaders, "body" => $responseBody, "responseInfo" => $responseInfo);
    }
    //Converts relative URLs to absolute ones, given a base URL.
    //Modified version of code found at http://nashruddin.com/PHP_Script_for_Converting_Relative_to_Absolute_URL
    function rel2abs($rel, $base) {
      if (empty($rel)) $rel = ".";
      if (parse_url($rel, PHP_URL_SCHEME) != "" || strpos($rel, "//") === 0) return $rel; //Return if already an absolute URL
      if ($rel[0] == "#" || $rel[0] == "?") return $base.$rel; //Queries and anchors
      extract(parse_url($base)); //Parse base URL and convert to local variables: $scheme, $host, $path
      $path = isset($path) ? preg_replace("#/[^/]*$#", "", $path) : "/"; //Remove non-directory element from path
      if ($rel[0] == "/") $path = ""; //Destroy path if relative url points to root
      $port = isset($port) && $port != 80 ? ":" . $port : "";
      $auth = "";
      if (isset($user)) {
        $auth = $user;
        if (isset($pass)) {
          $auth .= ":" . $pass;
        }
        $auth .= "@";
      }
      $abs = "$auth$host$port$path/$rel"; //Dirty absolute URL
      for ($n = 1; $n > 0; $abs = preg_replace(array("#(/.?/)#", "#/(?!..)[^/]+/../#"), "/", $abs, -1, $n)) {} //Replace '//' or '/./' or '/foo/../' with '/'
      return $scheme . "://" . $abs; //Absolute URL is ready.
    }
    //Proxify contents of url() references in blocks of CSS text.
    function proxifyCSS($css, $baseURL) {
      $sourceLines = explode("
    ", $css);
      $normalizedLines = [];
      foreach ($sourceLines as $line) {
        if (preg_match("/@imports+url/i", $line)) {
          $normalizedLines[] = $line;
        } else {
          $normalizedLines[] = preg_replace_callback(
            "/(@imports+)([^;s]+)([s;])/i",
            function($matches) use ($baseURL) {
              return $matches[1] . "url(" . $matches[2] . ")" . $matches[3];
            },
            $line);
        }
      }
      $normalizedCSS = implode("
    ", $normalizedLines);
      return preg_replace_callback(
        "/url((.*?))/i",
        function($matches) use ($baseURL) {
            $url = $matches[1];
            if (strpos($url, "'") === 0) {
              $url = trim($url, "'");
            }
            if (strpos($url, """) === 0) {
              $url = trim($url, """);
            }
            if (stripos($url, "data:") === 0) return "url(" . $url . ")"; //The URL isn't an HTTP URL but is actual binary data. Don't proxify it.
            return "url(" . PROXY_PREFIX . rel2abs($url, $baseURL) . ")";
        },
        $normalizedCSS);
    }
    //Proxify "srcset" attributes (normally associated with <img> tags.)
    function proxifySrcset($srcset, $baseURL) {
      $sources = array_map("trim", explode(",", $srcset)); //Split all contents by comma and trim each value
      $proxifiedSources = array_map(function($source) use ($baseURL) {
        $components = array_map("trim", str_split($source, strrpos($source, " "))); //Split by last space and trim
        $components[0] = PROXY_PREFIX . rel2abs(ltrim($components[0], "/"), $baseURL); //First component of the split source string should be an image URL; proxify it
        return implode($components, " "); //Recombine the components into a single source
      }, $sources);
      $proxifiedSrcset = implode(", ", $proxifiedSources); //Recombine the sources into a single "srcset"
      return $proxifiedSrcset;
    }
    //Extract and sanitize the requested URL, handling cases where forms have been rewritten to point to the proxy.
    if (isset($_POST["miniProxyFormAction"])) {
      $url = $_POST["miniProxyFormAction"];
      unset($_POST["miniProxyFormAction"]);
    } else {
      $queryParams = Array();
      parse_str($_SERVER["QUERY_STRING"], $queryParams);
      //If the miniProxyFormAction field appears in the query string, make $url start with its value, and rebuild the the query string without it.
      if (isset($queryParams["miniProxyFormAction"])) {
        $formAction = $queryParams["miniProxyFormAction"];
        unset($queryParams["miniProxyFormAction"]);
        $url = $formAction . "?" . http_build_query($queryParams);
      } else {
        $url = substr($_SERVER["REQUEST_URI"], strlen($_SERVER["SCRIPT_NAME"]) + 1);
      }
    }
    if (empty($url)) {
        if (empty($startURL)) {
          die("<html><head><title>miniProxy</title></head><body><h1>Welcome to miniProxy!</h1>miniProxy can be directly invoked like this: <a href="" . PROXY_PREFIX . $landingExampleURL . "">" . PROXY_PREFIX . $landingExampleURL . "</a><br /><br />Or, you can simply enter a URL below:<br /><br /><form onsubmit="if (document.getElementById('site').value) { window.location.href='" . PROXY_PREFIX . "' + document.getElementById('site').value; return false; } else { window.location.href='" . PROXY_PREFIX . $landingExampleURL . "'; return false; }" autocomplete="off"><input id="site" type="text" size="50" /><input type="submit" value="Proxy It!" /></form></body></html>");
        } else {
          $url = $startURL;
        }
    } else if (strpos($url, ":/") !== strpos($url, "://")) {
        $pos = strpos($url, ":/");
        $url = substr_replace($url, "://", $pos, strlen(":/"));
    }
    $scheme = parse_url($url, PHP_URL_SCHEME);
    if (empty($scheme)) {
      //Assume that any supplied URLs starting with // are HTTP URLs.
      if (strpos($url, "//") === 0) {
        $url = "http:" . $url;
      }
    } else if (!preg_match("/^https?$/i", $scheme)) {
        die('Error: Detected a "' . $scheme . '" URL. miniProxy exclusively supports http[s] URLs.');
    }
    //Validate the requested URL against the whitelist.
    $urlIsValid = count($whitelistPatterns) === 0;
    foreach ($whitelistPatterns as $pattern) {
      if (preg_match($pattern, $url)) {
        $urlIsValid = true;
        break;
      }
    }
    if (!$urlIsValid) {
      die("Error: The requested URL was disallowed by the server administrator.");
    }
    $response = makeRequest($url);
    $rawResponseHeaders = $response["headers"];
    $responseBody = $response["body"];
    $responseInfo = $response["responseInfo"];
    //If CURLOPT_FOLLOWLOCATION landed the proxy at a diferent URL than
    //what was requested, explicitly redirect the proxy there.
    $responseURL = $responseInfo["url"];
    if ($responseURL !== $url) {
      header("Location: " . PROXY_PREFIX . $responseURL, true);
      exit(0);
    }
    //A regex that indicates which server response headers should be stripped out of the proxified response.
    $header_blacklist_pattern = "/^Content-Length|^Transfer-Encoding|^Content-Encoding.*gzip/i";
    $responseHeaderBlocks = array_filter(explode("
    
    ", $rawResponseHeaders));
    $lastHeaderBlock = end($responseHeaderBlocks);
    $headerLines = explode("
    ", $lastHeaderBlock);
    foreach ($headerLines as $header) {
      $header = trim($header);
      if (!preg_match($header_blacklist_pattern, $header)) {
        header($header, false);
      }
    }
    //Prevent robots from indexing proxified pages
    header("X-Robots-Tag: noindex, nofollow", true);
    if ($forceCORS) {
      header("Access-Control-Allow-Origin: *", true);
      header("Access-Control-Allow-Credentials: true", true);
      //Handle CORS headers received during OPTIONS requests.
      if ($_SERVER["REQUEST_METHOD"] == "OPTIONS") {
        if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"])) {
          header("Access-Control-Allow-Methods: GET, POST, OPTIONS", true);
        }
        if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"])) {
          header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}", true);
        }
        //No further action is needed for OPTIONS requests.
        exit(0);
      }
    }
    $contentType = "";
    if (isset($responseInfo["content_type"])) $contentType = $responseInfo["content_type"];
    //This is presumably a web page, so attempt to proxify the DOM.
    if (stripos($contentType, "text/html") !== false) {
      //Attempt to normalize character encoding.
      $detectedEncoding = mb_detect_encoding($responseBody, "UTF-8, ISO-8859-1");
      if ($detectedEncoding) {
        $responseBody = mb_convert_encoding($responseBody, "HTML-ENTITIES", $detectedEncoding);
      }
      //Parse the DOM.
      $doc = new DomDocument();
      @$doc->loadHTML($responseBody);
      $xpath = new DOMXPath($doc);
      //Rewrite forms so that their actions point back to the proxy.
      foreach($xpath->query("//form") as $form) {
        $method = $form->getAttribute("method");
        $action = $form->getAttribute("action");
        //If the form doesn't have an action, the action is the page itself.
        //Otherwise, change an existing action to an absolute version.
        $action = empty($action) ? $url : rel2abs($action, $url);
        //Rewrite the form action to point back at the proxy.
        $form->setAttribute("action", rtrim(PROXY_PREFIX, "?"));
        //Add a hidden form field that the proxy can later use to retreive the original form action.
        $actionInput = $doc->createDocumentFragment();
        $actionInput->appendXML('<input type="hidden" name="miniProxyFormAction" value="' . htmlspecialchars($action) . '" />');
        $form->appendChild($actionInput);
      }
      //Proxify <meta> tags with an 'http-equiv="refresh"' attribute.
      foreach ($xpath->query("//meta[@http-equiv]") as $element) {
        if (strcasecmp($element->getAttribute("http-equiv"), "refresh") === 0) {
          $content = $element->getAttribute("content");
          if (!empty($content)) {
            $splitContent = preg_split("/=/", $content);
            if (isset($splitContent[1])) {
              $element->setAttribute("content", $splitContent[0] . "=" . PROXY_PREFIX . rel2abs($splitContent[1], $url));
            }
          }
        }
      }
      //Profixy <style> tags.
      foreach($xpath->query("//style") as $style) {
        $style->nodeValue = proxifyCSS($style->nodeValue, $url);
      }
      //Proxify tags with a "style" attribute.
      foreach ($xpath->query("//*[@style]") as $element) {
        $element->setAttribute("style", proxifyCSS($element->getAttribute("style"), $url));
      }
      //Proxify "srcset" attributes in <img> tags.
      foreach ($xpath->query("//img[@srcset]") as $element) {
        $element->setAttribute("srcset", proxifySrcset($element->getAttribute("srcset"), $url));
      }
      //Proxify any of these attributes appearing in any tag.
      $proxifyAttributes = array("href", "src");
      foreach($proxifyAttributes as $attrName) {
        foreach($xpath->query("//*[@" . $attrName . "]") as $element) { //For every element with the given attribute...
          $attrContent = $element->getAttribute($attrName);
          if ($attrName == "href" && preg_match("/^(about|javascript|magnet|mailto):|#/i", $attrContent)) continue;
          if ($attrName == "src" && preg_match("/^(data):/i", $attrContent)) continue;
          $attrContent = rel2abs($attrContent, $url);
          $attrContent = PROXY_PREFIX . $attrContent;
          $element->setAttribute($attrName, $attrContent);
        }
      }
    
      $head = $xpath->query("//head")->item(0);
      $body = $xpath->query("//body")->item(0);
      $prependElem = $head != null ? $head : $body;
      if ($prependElem != null) {
        $scriptElem = $doc->createElement("script",
          '(function() {
            if (window.XMLHttpRequest) {
              function parseURI(url) {
                var m = String(url).replace(/^s+|s+$/g, "").match(/^([^:/?#]+:)?(//(?:[^:@]*(?::[^:@]*)?@)?(([^:/?#]*)(?::(d*))?))?([^?#]*)(?[^#]*)?(#[sS]*)?/);
                // authority = "//" + user + ":" + pass "@" + hostname + ":" port
                return (m ? {
                  href : m[0] || "",
                  protocol : m[1] || "",
                  authority: m[2] || "",
                  host : m[3] || "",
                  hostname : m[4] || "",
                  port : m[5] || "",
                  pathname : m[6] || "",
                  search : m[7] || "",
                  hash : m[8] || ""
                } : null);
              }
              function rel2abs(base, href) { // RFC 3986
                function removeDotSegments(input) {
                  var output = [];
                  input.replace(/^(..?(/|$))+/, "")
                    .replace(//(.(/|$))+/g, "/")
                    .replace(//..$/, "/../")
                    .replace(//?[^/]*/g, function (p) {
                      if (p === "/..") {
                        output.pop();
                      } else {
                        output.push(p);
                      }
                    });
                  return output.join("").replace(/^//, input.charAt(0) === "/" ? "/" : "");
                }
                href = parseURI(href || "");
                base = parseURI(base || "");
                return !href || !base ? null : (href.protocol || base.protocol) +
                (href.protocol || href.authority ? href.authority : base.authority) +
                removeDotSegments(href.protocol || href.authority || href.pathname.charAt(0) === "/" ? href.pathname : (href.pathname ? ((base.authority && !base.pathname ? "/" : "") + base.pathname.slice(0, base.pathname.lastIndexOf("/") + 1) + href.pathname) : base.pathname)) +
                (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +
                href.hash;
              }
              var proxied = window.XMLHttpRequest.prototype.open;
              window.XMLHttpRequest.prototype.open = function() {
                  if (arguments[1] !== null && arguments[1] !== undefined) {
                    var url = arguments[1];
                    url = rel2abs("' . $url . '", url);
                    if (url.indexOf("' . PROXY_PREFIX . '") == -1) {
                      url = "' . PROXY_PREFIX . '" + url;
                    }
                    arguments[1] = url;
                  }
                  return proxied.apply(this, [].slice.call(arguments));
              };
            }
          })();'
        );
        $scriptElem->setAttribute("type", "text/javascript");
        $prependElem->insertBefore($scriptElem, $prependElem->firstChild);
      }
      echo "<!-- Proxified page constructed by miniProxy -->
    " . $doc->saveHTML();
    } else if (stripos($contentType, "text/css") !== false) { //This is CSS, so proxify url() references.
      echo proxifyCSS($responseBody, $url);
    } else { //This isn't a web page or CSS, so serve unmodified through the proxy with the correct headers (images, JavaScript, etc.)
      header("Content-Length: " . strlen($responseBody), true);
      echo $responseBody;
    }
    View Code

    <dd><a href="http://www.678fuzhu.com" title="" target="_blank">678辅助网</a></dd>
    <dd><a href="https://www.xd0.com" title="" target="_blank">小刀娱乐网</a></dd>
    <dd><a href="http://www.tv432.com/" title="" target="_blank">黑米影院</a></dd>
    <dd><a href="http://www.pk1xia.com" title="" target="_blank">pk游戏网</a></dd>
    <dd><a href="https://www.678fzw.com" title="" target="_blank">678辅助网</a></dd>
    <dd><a href="http://www.kxdao.net" title="" target="_blank">科学刀论坛</a></dd>
    <dd><a href="https://www.kjsv.com" title="" target="_blank">小K娱乐网</a></dd>
    <dd><a href="https://www.404v.com" title="" target="_blank">善恶资源网</a></dd>
    <dd><a href="https://www.yzd1.com" title="" target="_blank">影子资源网</a></dd>
    <dd><a href="https://dwz.lc/c8wLE" title="" target="_blank">好牛娱乐网</a></dd>
    <dd><a href="http://www.52fzw.com" title="" target="_blank">我爱辅助网</a></dd>
    <dd><a href="https://www.haojiyou.la" title="" target="_blank">好基友乐园</a></dd>
    <dd><a href="https://www.678cn.comyoulian奇特吧.html" title="" target="_blank">奇特吧</a></dd>
    <dd><a href="https://www.678cn.com" title="" target="_blank">梅花辅助网</a></dd>
    <dd><a href="https://www.nanfengyl.com#1" title="" target="_blank">南风娱乐网</a></dd>
    <dd><a href="http://qia.la/" title="" target="_blank">刀网同款防御</a></dd>
    <dd><a href="https://www.115z.com/" title="" target="_blank">115资源网</a></dd>
    <dd><a href="https://www.5izyw.com" title="" target="_blank">小超辅助网</a></dd>
    <dd><a href="https://www.678cn.com/4252.html" title="" target="_blank">科学侠辅助</a></dd>
    <dd><a href="https://www.678cn.com/zhide/5337.html" title="" target="_blank">末世辅助网</a></dd>
    <dd><a href="https://www.xbyuan.com/" title="" target="_blank">线报院</a></dd>
    <dd><a href="http://www.tv665.com" title="" target="_blank">665影院网</a></dd>
    <dd><a href="http://www.54fzw.com" title="" target="_blank">我爱辅助</a></dd>
    </dl>

  • 相关阅读:
    jQuery EasyUI API 中文文档 数字框(NumberBox)
    jQuery EasyUI API 中文文档 数值微调器(NumberSpinner)
    jQuery EasyUI API 中文文档 日期时间框(DateTimeBox)
    jQuery EasyUI API 中文文档 微调器(Spinner)
    jQuery EasyUI API 中文文档 树表格(TreeGrid)
    jQuery EasyUI API 中文文档 树(Tree)
    jQuery EasyUI API 中文文档 属性表格(PropertyGrid)
    EntityFramework 数据操作
    jQuery EasyUI API 中文文档 对话框(Dialog)
    jQuery EasyUI API 中文文档 组合表格(ComboGrid)
  • 原文地址:https://www.cnblogs.com/csnd/p/11466725.html
Copyright © 2011-2022 走看看