我设法收集了一些资源来弄清楚如何做到这一点。我使用共享托管提供商,因此无法访问服务器配置(httpd.conf)。我只能使用 .htaccess 来完成代理。这个例子是针对一个 WordPress 网站的,我希望大部分内容由 origin.example.com 提供,但会有一些页面本地提供,就像叠加层一样。您也可以采用另一种方式,仅使用不同的 RewriteCond 规则代理特定的子目录。
需要知道的事情:
- 您不能在 .htaccess 中使用 ProxyPass 或 ProxyPassReverse,因此我们必须使用其他方法来模拟它们所做的事情。
- 如果您的提供商未启用 SSLProxyEngine,则无法通过 HTTPS 进行代理调用,因此如果您担心中间人攻击,您将失去一些安全性。如果源服务器是内部的,则可能不存在此问题。您还可以在源服务器上使用 .htaccess 强制从除代理服务器以外的任何地方都使用 HTTPS。
- 您需要重写标头
- 您需要重写来自源服务器的 HTML,并且需要在源服务器上完成。您可以将其限制为某些 IP(即代理的 IP),以便在其他地方访问时不会出现问题。
我的要求:
我想让对 proxy.example.com 的调用提供 origin.example.com 的内容。在我的情况下,我想映射除了一些例外以外的所有内容。如果您只想映射网站的一部分,请相应地调整规则。
如何操作:
- 在 proxy.example.com 上配置 .htaccess 文件,将所有 URI 代理到 origin.example.com 上。我希望能够登录 proxy.example.com,因此我不会重写 /wp-admin 或 /wp-login.php。在我的情况下,我有一个 /programs/ 部分,我希望代理服务器本身(也是 WordPress 实例)提供服务。通过检查 REDIRECT_STATUS 来避免循环。
# I force everything coming into proxy.example.com to be HTTPS <IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] </IfModule> <IfModule mod_proxy.c>
# Redirect access for / (or any index) to the origin. NOTE target is http:// without SSLProxyEngine
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(index\.(php|html|cgi))?$ http://origin.example.com/ [P]
# Do NOT redirect these patterns
RewriteCond %{REQUEST_URI} !^/wp-admin/
RewriteCond %{REQUEST_URI} !^/wp-login.php
RewriteCond %{REQUEST_URI} !^/programs/
# Redirect everything else. NOTE target is http:// without SSLProxyEngine
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.+)$ "http://origin.example.com/$1" [P]
# Mimic ProxyPassReverse. Fix the headers. Force to be https.
Header edit Location ^https?://origin\.example\.com/(.*)$ https://proxy.example.com/$1
Header edit* Link https?://origin\.example\.com/ https://proxy.example.com/ </IfModule>
- 仅针对代理服务器的IP,重写HTML本身中的任何引用。此示例适用于WordPress网站。
从 WordPress过滤器以修改最终HTML输出中窃取
2a)添加一个必须使用插件来添加“final_output”钩子。在wp-content/mu-plugins/buffer.php中添加一个文件:
<?php
/** * Output Buffering * * Buffers the entire WP process, capturing
the final output for manipulation. */
ob_start();
add_action('shutdown', function() {
$final = '';
// We'll need to get the number of ob levels we're in, so that we can iterate over each, collecting
// that buffer's output into the final output.
$levels = ob_get_level();
for ($i = 0; $i < $levels; $i++) {
// NOTE: Use only one of the two lines below
// that has your output come out in the correct order.
//$final .= ob_get_clean();
$final = ob_get_clean() . $final;
}
// Apply any filters to the final output
echo apply_filters('final_output', $final); }, 0); ?>
2b) 将以下 PHP 添加到 wp-content/themes/yourthemenamehere/functions.php 中。它使用上面的 'final_output' 钩子。(PHP 5.3 或更高版本需要使用匿名函数。)
add_filter('final_output', function($output) {
// IP of the proxy server
$WWW_IP = “4.4.4.4”;
//$WWW_IP = “4.4.2.2”; // My workstation, for testing purpose only
if ($_SERVER['REMOTE_ADDR'] == $WWW_IP) {
// Force HTTPS when rewriting
$output = str_replace('http://origin.example.com', 'https://proxy.example.com’, $output);
// Catch anything that wasn’t a URL
return str_replace(‘origin.example.com, 'proxy.example.com', $output);
}
return $output;
});
如果一切顺利,您现在应该看到从 origin.example.com 提供的内容被 proxy.example.com 代理了。
我仍在测试中,如果您发现错误或遗漏,请添加评论。
RewriteRule ^(foo|bar)/?$ http://example.com/$1 [P,L]
- anubhavaL
标志,它只表示不需要测试更多规则。 - Paul DraperP
会强制添加L
。 - Titou