У меня много проблем с правильной настройкой Apache mod_proxy.so для работы по желанию ...
Основная идея - создать прокси-сервер на локальном компьютере в сети, который будет иметь возможность обрабатывать клиентский запрос (клиент, подключенный через этот подготовленный Apache прокси) на PHP. Кроме того, он будет иметь возможность обрабатывать ответы сервера на PHP.
Это 2 функции, и они независимы друг от друга.
Позвольте мне представить небольшую схему того, чего мне нужно достичь:
Как видите, здесь два пути: синий и красный.
Что касается синего, я в основном подключил клиента (машина B - сотовый телефон) к моей локальной сети (домашней) и настроил его для работы через прокси-сервер, которым является машина A (персональный компьютер) в той же сети.
Итак, скажем (не DHCP):
Машина А: 192.168.1.40 -> Apache работает на этом компьютере и настроен на прослушивание порта 80.
Машина B (сотовый телефон): 192.168.1.75 -> настроен для прохождения через прокси, который имеет IP 192.168.1.75 и порт 80 (в основном, машина A).
После правильной настройки Apache, которая заключается в том, чтобы удалить "#" из httpd.conf в строках для mod_proxy.so (основной рабочий), mod_proxy_connect.so (SSL, allowCONNECT, ...) и mod_proxy_http.so (необходимо для обрабатывать HTTP-запросы / ответы) и иметь в моем случае такие строки:
# Implements a proxy/gateway for Apache.
Include "conf/extra/httpd-proxy.conf"
# Various default settings
Include "conf/extra/httpd-default.conf"
# Secure (SSL/TLS) connections
Include "conf/extra/httpd-ssl.conf"
Это дает мне возможность настроить файл httpd-proxy.conf для подготовки прямого или обратного прокси.
Так что я не уверен, нужен ли мне прямой прокси или обратный.
Для прямого прокси я сделал это:
<IfModule proxy_module>
<IfModule proxy_http_module>
#
# FORWARD Proxy
#
#ProxyRequests Off
ProxyRequests On
ProxyVia On
<Proxy *>
Order deny,allow
# Allow from all
Deny from all
Allow from 192.168.1
</Proxy>
</IfModule>
</IfModule>
который обычно передает все пакеты на сервер и обратно клиенту. Я могу отлично отследить это (и проверить, что работает), глядя на "access.log" из Apache. Любой запрос, который я делаю с помощью мобильного телефона, появляется в журнале Apache. Так что работает.
Но вот проблема:
Я много читал об этом. Я подробно прочитал официальный сайт Apache о mod_proxy. И я много искал на форумах, но безуспешно.
Итак, я подумал о первом приближении:
1) Перенаправить прокси в Apache, передает все пакеты, и их невозможно обработать. Кажется, это правда, а как насчет обратного прокси?
Я представил себе что-то вроде:
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass http://www.google.com http://www.yahoo.com
ProxyPassReverse http://www.google.com http://www.yahoo.com
это просто тест, но это должно привести к тому, что на моем мобильном телефоне при попытке перейти в Google я должен перейти на Yahoo, не так ли? Но нет. Не работает.
Итак, вы действительно видите, что ВСЕ примеры обратного прокси Apache выглядят так:
ProxyPass /foo http://foo.example.com/bar
ProxyPassReverse /foo http://foo.example.com/bar
Это означает, что любой запрос в локальном контексте будет решен в удаленном месте.
Но мне было нужно обратное! Дело в том, что когда я запрашиваю удаленный сайт на моем телефоне, я решаю этот запрос на своем локальном сервере (Apache), чтобы обработать его с помощью модуля PHP.
Итак, если это прямой прокси, мне нужно сначала пройти через PHP. Если это обратный прокси, мне нужно изменить направление «движения» на локальный сервер, чтобы сначала обрабатывать его на PHP.
Тогда на ум приходит второй вариант:
2) Я видел что-то вроде:
<Proxy http://example.com/foo/*>
SetOutputFilter INCLUDES
</Proxy>
И я начал искать SetOutputFilter, SetInputFilter, AddOutputFilter и AddInputFilter.
Но я действительно не знаю, как мне это использовать.
Кажется, это хорошо или решение для меня, потому что с чем-то вроде этого я должен иметь возможность добавить фильтр ввода для обработки на PHP клиентских запросов и отправки обратно клиенту того, что я запрограммировал / хочу (а не ответ удаленного сервера ) какой СИНИЙ путь на схеме, и у меня должна быть возможность добавить выходной фильтр, который, кажется, дает мне возможность обрабатывать ответ удаленного сервера перед его отправкой клиенту, который должен быть КРАСНЫЙ путь по схеме.
Красный путь, это просто чтобы прочитать ответы сервера и поиграть с ними. Но не более того. Синий путь - самый важный. Потому что после обработки запросов я отправлю клиенту все, что захочу.
Извините за этот удивительно большой пост, но мне нужно было объяснить его как можно лучше.
Надеюсь, кто-то поймет мою проблему и поможет мне ее решить!
@Sarek прав, но вопрос в том, как обрабатывать прокси-запросы с помощью PHP (из Apache mod_proxy), а не в том случае, если Apache - правильный инструмент для этого.
Чтобы использовать PHP с Apache в качестве прокси, я использую (для этого требуются mod_proxy и mod_rewrite) в httpd.conf
:
# Forward proxy server
<VirtualHost *:8080>
ProxyRequests On
ProxyVia On
<Proxy *>
Order deny,allow
Deny from all
Allow from 192.168
RewriteEngine On
RewriteCond %{REQUEST_URI} !/pac.php
RewriteRule ^ /endpoint.php [L]
</Proxy>
</VirtualHost>
Затем в /pac.php
(которые определяют PAC содержимое файла):
<?php header('Content-Type: application/x-javascript-config') ?>
function FindProxyForURL(url, host)
{
return "PROXY <?php echo $_SERVER['SERVER_ADDR'] ?>:<?php echo $_SERVER['SERVER_PORT'] ?>; DIRECT";
}
Он используется для настройки прокси на машине B (прокси-клиент). Использовать http://192.168.1.40:8080/pac.php
. При этом клиент всегда будет использовать прокси для любых доменов / ip (например, 127.0.0.1, localhost, * .local и т. Д.). Примечание. Приложения IE и .Net по-прежнему нужно писать только для localhost
и 127.0.0.1
конечная точка FQDN: http://localhost.
и http://127.0.0.1.
.
Наконец в /endpoint.php
:
<?php
// Don't handle domain existance
$url = $_SERVER['REQUEST_URI'];
$url_parts = parse_url($url);
// Some security checks (no local file...)
if(false === $url_parts || empty($url_parts['scheme']) || !in_array($url_parts['scheme'], array('http', 'https'))){
die();
}
$headers_raw = '';
foreach ($_SERVER as $name => $value)
{
if (substr($name, 0, 5) == 'HTTP_')
{
$name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))));
$headers_raw .= $name . ': ' . $value . "\r\n";
} else if ($name == "CONTENT_TYPE") {
$headers_raw .= 'Content-Type: ' . $value . "\r\n";
} else if ($name == "CONTENT_LENGTH") {
$headers_raw .= 'Content-Length: ' . $value . "\r\n";
}
}
// http://php.net/manual/en/context.http.php
$context = stream_context_create(array(
'http' => array(
'method' => $_SERVER['REQUEST_METHOD'],
'header' => $headers_raw,
'ignore_errors' => true,
'content' => file_get_contents('php://input')
)
));
$content = file_get_contents($url, false, $context);
$content_type = 'application/octet-stream';// "text/html"
$content_type_raw = $content_type;// "text/html; charset=UTF-8"
foreach($http_response_header as $response_header){
if('Content-Type:' == substr($response_header, 0, 13)){
$content_type_raw = substr($response_header, 14);
$content_type = strstr($content_type_raw, ';', true);
header($response_header);
}
elseif('Content-Encoding:' == substr($response_header, 0, 17) && 'gzip' == substr($response_header, 18, 4))
{
//Now lets uncompress the compressed data
$content = gzinflate(substr($content, 10, -8));
}
elseif('Content-Length:' == substr($response_header, 0, 15))
{
//Skip it
}
else{
header($response_header);
}
}
// Content transforms
//var_dump($url_parts);exit();
if('text/html' == $content_type){
echo str_replace('cat', 'dog', $content);
}else{
echo $content;
}
Это пример, не используйте его в производстве. Он не обрабатывает недопустимые / тайм-аут домены / IP.
При этом вы можете переписать запрошенный URL (прокси может обслуживать содержимое http://google.com/search?q=dog
для URL http://google.com/search?q=cat
, забавная шутка) и обновите контент (например, удалите рекламу, вставьте JS / CSS и т. д.)
Итак, во-первых: Apache - неподходящий инструмент!
Apache - это веб-сервер, а не прокси-сервер. Да, он поставляется с модулем прокси, но в первую очередь это веб-сервер.
Лучше заглянуть в настоящий прокси-сервер, такой как squid. А в squid вам нужна функция под названием «Адаптация контента»: