У меня установлено веб-приложение (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