Назад | Перейти на главную страницу

Apache RewriteRule для прокси

У меня установлено веб-приложение (ClockingIT), которое действует на основе используемого поддомена. Поскольку мы хотим использовать SSL и не имеем сертификата с подстановочными знаками, это не очень удобно для нас :-) Поэтому я подумал об использовании функций Apache mod_proxy и mod_rewrite.

Чтобы быть более точным, я хочу, чтобы URL-адрес Xttps: //example.com/cit/ (внешний) отображал содержимое Xttp: //test.example.com: 3000 / (внутренний).

Вот моя установка:

   <VirtualHost *:443>
     ServerName example.com

     (SSL setup, etc)

     SSLProxyEngine On
     UseCanonicalName Off
     ProxyRequests Off   
     ProxyPreserveHost Off # or On, makes no difference

     RewriteEngine On
     RewriteRule      ^/cit$         Xttp://test.example.com:3000/ [P,NC]
     RewriteRule      ^/cit/(.*)$    Xttp://test.example.com:3000/$1 [P,NC]
     ProxyPassReverse /cit/          Xttp://test.example.com:3000/

test.example.com не определен на DNS-сервере, но установлен в / etc / hosts для сопоставления с 127.0.0.1. Если я сделаю «w3m Xttp: //test.example.com: 3000 /» на сервере, я получу правильную веб-страницу. Однако, если я получу доступ https://example.com/cit/ в браузере рабочего стола я не вижу нужную веб-страницу. Веб-приложение получает запрос, но, похоже, думает, что запрос был для домена example.com, и обслуживает страницу по умолчанию вместо предполагаемого «тестового» содержимого поддомена. Кажется, почему-то прокси не проходит через домен test.example.com, хотя согласно документации должен. Вместо RewriteRule я также попробовал директиву ProxyPass, но с тем же результатом.

Что мне не хватает?

(Если уместно, ClockingIT - это приложение Ruby on Rails, обслуживаемое через Mongrel)

P.S .: s / Xttp / http / g - ServerFault не понравился мне, когда я использовал косую черту косой черты http более одного раза в моем вопросе ;-)

Редактировать:

После просмотра данных трафика с помощью tcpflow проблема, похоже, заключается в том, что Apache отправляет на порт 3000 следующее:

GET / HTTP/1.1
Host: test.example.com:3000
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7
Cookie: _session_id=99f5f70d684c2186e64c5ebb8f69d574
Via: 1.1 example.com
X-Forwarded-For: 1.2.3.4
X-Forwarded-Host: example.com
X-Forwarded-Server: example.com

Используя "telnet localhost 3000" и вставив вышеуказанное, я получаю перенаправление. Если я повторю это и опущу строку X-Forwarded-Host :, я получу нужную страницу. Итак, моя установка действительно работает, но ClockingIT, похоже, основывает свое решение на значении X-Forwarded-Host. Как я могу предотвратить включение этого?

В Apache 2.4 и более поздних версиях есть директива для удаления заголовков X-Forwarded- *.

ProxyAddHeaders off

https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxyaddheaders

Меня это укусило. Это действительно досадно странно.

Mod_proxy Apache добавляет заголовок x-forwarded-host ко всем исходящим запросам. Его нельзя отключить с помощью HeaderRequest unset x-forwarded-host, ни с помощью ProxyVia, ни с помощью ProxyPreseveHost. Ни с чем еще я не мог найти.

Когда Rails видит этот заголовок, он использует Это для создания заголовка Location: любых HTTP-ответов. Для справки, в версии Rails vendor'd с Webistrano 1.4 (приложение, которое сбивало меня с толку с помощью mod_proxy) соответствующий код, похоже, находится в строке 88 vendor / rails / actionpack / lib / action_controller / cgi_process.rb, внутри функция host_with_port_without_standard_port_handling.

Теперь посмотрим на описанный типичный пример ProxyPass и ProxyPassReverse. где угодно в сети - включая (по сути) ваш вопрос и альтернативный ответ, приведенный здесь:

<VirtualHost *:80>
ServerName proxy.domain.tld
ProxyPass /app1/ http://app1host.internal/
ProxyPassReverse /app1/ http://app1host.internal/
</VirtualHost>

Видите проблему? Это линия PPR ..

Поскольку Rails / ActionPack / dasFramework, по его мнению, пытается Помогите вы, "исправив" заголовок Location :, вторая половина строки PPR неверна: вместо соответствия

Location: http://app1host.internal/redirected/path

mod_proxy будет фактически видеть

Location: http://proxy.domain.tld/redirected/path

К счастью, исправить это довольно просто - измените приведенную выше конфигурацию vhost на:

<VirtualHost *:80>
ServerName proxy.domain.tld
ProxyPass /app1/ http://app1host.internal/
ProxyPassReverse /app1/ http://proxy.domain.tld/
</VirtualHost>

Если у вас есть более одного приложения, проксируемого в vhost, имейте в виду, что вам нужно поместить PPR в разделы Location, по крайней мере, чтобы различать их.

Возможно, вам будет проще использовать ProxyPass вместо mod_rewrite, чтобы делать то, что вы пытаетесь сделать. Возможно, это не решит вашу проблему, но, безусловно, сделает ваш файл конфигурации немного чище:

ProxyPass        /cit/          http://test.example.com:3000/
ProxyPassReverse /cit/          http://test.example.com:3000/

Вы можете попробовать использовать что-то вроде tcpflow или wirehark, чтобы точно узнать, какие заголовки использует apache для проксирования запроса.

Вы уверены, что ProxyPreserveHost директива не имеет значения? Если он включен, заголовок хоста из начального запроса будет сохранен в запросе, отправленном на внутренний сервер, что вы и описываете.

Видеть:

http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypreservehost