Ошибка Rails + Passenger + Nginx Запрос источника (domainname.com) не соответствует запросу Base_url (IP-адрес)

Настройка: Rails 5.1.3, Dreamhost VPS с Passenger и Nginx. Поскольку это VPS, у меня нет root-доступа для выполнения каких-либо функций, требующих root-прав.

Ситуация: В настоящее время я переделал предыдущее приложение rails с функциональностью ActionCable. Более ранняя конфигурация была с Apache вместо Nginx для http-сервера. Все отлично работает кроме вебсокетов, а статей я читал не мало, все подтверждающие действие кабели + апач не подойдут.

В этот момент я переключился на NginX. С NginX мое первое наблюдение заключалось в том, что приложение постоянно пытается выполнить процесс «получить кабель/» и не может обновиться до веб-сокета. Прочитав различные обсуждения, мне удалось решить эту проблему с помощью:

location /cable {
    proxy_pass http://127.0.0.1:8000/cable;
    proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

}

Поскольку у меня нет прав root для доступа к обычному файлу dt/etc/nginx/.../***.conf, с пакетом dreamhost VPS я могу добавить файл в /home/username/nginx/(appname. com)/(any-file-name.conf), и это будет добавлено к «серверному блоку» nginx в соответствии с документацией dreamhost.

^^ Таким образом, один только приведенный выше блок кода в файле с именем «redis.conf» в этом каталоге решил проблему с кабелями действий. Удачно запускается стриминг, на каналах все нормально.

Позже я понял, что основная проблема заключается в том, что я не могу выполнять какие-либо действия по созданию, обновлению, уничтожению — все, что требует методов POST или DELETE, поскольку это приводит к ошибке токена аутентификации, говорящей: «Источник запроса (http://siik .io — это имя приложения и домена) не соответствует request.base_url (http://127.0.0.1).

Детальная ошибка:

I, [2017-09-11T03:27:28.623080 #7273]  INFO -- : [50a21156-0333-413e-94b

8-07b791c209fc] Completed 200 OK in 83ms (Views: 56.0ms | ActiveRecord: 16.6ms)
I, [2017-09-11T03:27:31.950732 #7273]  INFO -- : [dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] Started POST "/conversations/1/messages" for 106.208.156.243 at 2017-09-11 03:27:31 -0700
I, [2017-09-11T03:27:31.953339 #7273]  INFO -- : [dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] Processing by MessagesController#create as JS
I, [2017-09-11T03:27:31.953511 #7273]  INFO -- : [dd8e08f7-f28b-497b-9ae9-e57a6a45c35d]   Parameters: {"utf8"=>"✓", "message"=>{"user_id"=>"1", "body"=>"sdfgh"}, "commit"=>"Send", "conversation_id"=>"1"}
W, [2017-09-11T03:27:31.954325 #7273]  WARN -- : [dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] HTTP Origin header (http://www.siik.io) didn't match request.base_url (http://127.0.0.1:8000)
I, [2017-09-11T03:27:31.954890 #7273]  INFO -- : [dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms)
F, [2017-09-11T03:27:31.956888 #7273] FATAL -- : [dd8e08f7-f28b-497b-9ae9-e57a6a45c35d]   
F, [2017-09-11T03:27:31.956969 #7273] FATAL -- : [dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
F, [2017-09-11T03:27:31.957017 #7273] FATAL -- : [dd8e08f7-f28b-497b-9ae9-e57a6a45c35d]   
F, [2017-09-11T03:27:31.957126 #7273] FATAL -- : [dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_controller/metal/request_forgery_protection.rb:195:in `handle_unverified_request'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_controller/metal/request_forgery_protection.rb:227:in `handle_unverified_request'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] devise (4.3.0) lib/devise/controllers/helpers.rb:253:in `handle_unverified_request'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_controller/metal/request_forgery_protection.rb:222:in `verify_authenticity_token'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] activesupport (5.1.3) lib/active_support/callbacks.rb:413:in `block in make_lambda'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] activesupport (5.1.3) lib/active_support/callbacks.rb:197:in `block (2 levels) in halting'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/abstract_controller/callbacks.rb:12:in `block (2 levels) in <module:Callbacks>'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] activesupport (5.1.3) lib/active_support/callbacks.rb:198:in `block in halting'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] activesupport (5.1.3) lib/active_support/callbacks.rb:507:in `block in invoke_before'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] activesupport (5.1.3) lib/active_support/callbacks.rb:507:in `each'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] activesupport (5.1.3) lib/active_support/callbacks.rb:507:in `invoke_before'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] activesupport (5.1.3) lib/active_support/callbacks.rb:130:in `run_callbacks'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/abstract_controller/callbacks.rb:19:in `process_action'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_controller/metal/rescue.rb:20:in `process_action'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_controller/metal/instrumentation.rb:32:in `block in process_action'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] activesupport (5.1.3) lib/active_support/notifications.rb:166:in `block in instrument'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] activesupport (5.1.3) lib/active_support/notifications/instrumenter.rb:21:in `instrument'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] activesupport (5.1.3) lib/active_support/notifications.rb:166:in `instrument'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_controller/metal/instrumentation.rb:30:in `process_action'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_controller/metal/params_wrapper.rb:252:in `process_action'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] activerecord (5.1.3) lib/active_record/railties/controller_runtime.rb:22:in `process_action'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/abstract_controller/base.rb:124:in `process'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionview (5.1.3) lib/action_view/rendering.rb:30:in `process'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_controller/metal.rb:189:in `dispatch'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_controller/metal.rb:253:in `dispatch'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_dispatch/routing/route_set.rb:49:in `dispatch'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_dispatch/routing/route_set.rb:31:in `serve'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_dispatch/journey/router.rb:46:in `block in serve'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_dispatch/journey/router.rb:33:in `each'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_dispatch/journey/router.rb:33:in `serve'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_dispatch/routing/route_set.rb:834:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] remotipart (1.3.1) lib/remotipart/middleware.rb:32:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] warden (1.2.7) lib/warden/manager.rb:36:in `block in call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] warden (1.2.7) lib/warden/manager.rb:35:in `catch'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] warden (1.2.7) lib/warden/manager.rb:35:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] rack (2.0.3) lib/rack/etag.rb:25:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] rack (2.0.3) lib/rack/conditional_get.rb:38:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] rack (2.0.3) lib/rack/head.rb:12:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] rack (2.0.3) lib/rack/session/abstract/id.rb:232:in `context'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] rack (2.0.3) lib/rack/session/abstract/id.rb:226:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_dispatch/middleware/cookies.rb:613:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_dispatch/middleware/callbacks.rb:26:in `block in call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] activesupport (5.1.3) lib/active_support/callbacks.rb:97:in `run_callbacks'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_dispatch/middleware/callbacks.rb:24:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_dispatch/middleware/debug_exceptions.rb:59:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_dispatch/middleware/show_exceptions.rb:31:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] railties (5.1.3) lib/rails/rack/logger.rb:36:in `call_app'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] railties (5.1.3) lib/rails/rack/logger.rb:24:in `block in call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] activesupport (5.1.3) lib/active_support/tagged_logging.rb:69:in `block in tagged'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] activesupport (5.1.3) lib/active_support/tagged_logging.rb:26:in `tagged'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] activesupport (5.1.3) lib/active_support/tagged_logging.rb:69:in `tagged'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] railties (5.1.3) lib/rails/rack/logger.rb:24:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_dispatch/middleware/remote_ip.rb:79:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_dispatch/middleware/request_id.rb:25:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] rack (2.0.3) lib/rack/method_override.rb:22:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] rack (2.0.3) lib/rack/runtime.rb:22:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] activesupport (5.1.3) lib/active_support/cache/strategy/local_cache_middleware.rb:27:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] actionpack (5.1.3) lib/action_dispatch/middleware/executor.rb:12:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] rack (2.0.3) lib/rack/sendfile.rb:111:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] railties (5.1.3) lib/rails/engine.rb:522:in `call'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] passenger (5.1.8) src/ruby_supportlib/phusion_passenger/rack/thread_handler_extension.rb:97:in `process_request'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] passenger (5.1.8) src/ruby_supportlib/phusion_passenger/request_handler/thread_handler.rb:160:in `accept_and_process_next_request'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] passenger (5.1.8) src/ruby_supportlib/phusion_passenger/request_handler/thread_handler.rb:113:in `main_loop'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] passenger (5.1.8) src/ruby_supportlib/phusion_passenger/request_handler.rb:416:in `block (3 levels) in start_threads'
[dd8e08f7-f28b-497b-9ae9-e57a6a45c35d] passenger (5.1.8) src/ruby_supportlib/phusion_passenger/utils.rb:113:in `block in create_thread_and_abort_on_exception'

НО, когда я захожу на сайт через http://siik.io:8000, ВСЕ работает отлично, даже бит веб-сокетов без необходимости в файле redis.conf.

Я просмотрел неделю различных исправлений и документации и не смог найти решение для этого. Я думаю, что основным требованием является добавление дополнительных заголовков в блок location/{} для добавления в файл nginx.conf... (Я перечислил несколько примеров, которые пробовал ниже.)

listen 80;
listen *:80;
server_name siik.io www.siik.io http://siik.io;
location / {

        proxy_redirect off;
        proxy_set_header Host $host:8000;

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;


        proxy_http_version 1.1;

        proxy_set_header   X-Real-IP $remote_addr:8000;
        proxy_set_header  X-Forwarded-Port $server_port;

        proxy_pass http://127.0.0.1:8000/;
}

.. Итак, я в основном пробую различные комбинации и перестановки для вышеуказанных значений, чтобы увидеть, что работает, потому что, очевидно, я понятия не имею, как это работает - у меня есть некоторые концептуальные знания об обратном проксировании и http-серверах.

Да, я знаю, что request.origin == request.base_url относится к биту rails Protect_from_forgery, я не чувствую, что его отключение является решением, хотя я где-то читал, что включение правильных заголовков решит эту проблему. Я пробовал несколько вариантов этих наборов заголовков, и ни один из них не работал, и мне интересно, должно ли включение правильных заголовков достичь точки, в которой заголовок источника http изменится с domainname.io на IP-адрес или request.base_url изменится с IP-адрес доменному имени??

Ах да, когда я добавляю блок location/{} в новый файл proxy.conf рядом с redis.conf, он полностью ломается. Сайт через domainname.io отказывается подключаться, а domainname.io:8000 работает отлично. Даже пустой блок под location / ломает его - я проверял, не вызывают ли его какие-либо конкретные команды proxy_set - но нет. Просто биты "location/{}" разбивают его - может быть, это ожидаемо?

Почему это работает отлично, когда я обращаюсь к нему через siik.io:8000 с явным указанием номера порта?

Любая помощь ОЧЕНЬ приветствуется!!!!


person Shanthanu Varma    schedule 11.09.2017    source источник


Ответы (2)


Вам не нужно запускать кабельный сервер действий на другом порту, попробуйте выполнить следующие инструкции: https://www.phusionpassenger.com/library/config/nginx/action_cable_integration/

Скопировано здесь согласно ПРАВИЛАМ™:

Запуск сервера Action Cable на том же хосте и порту под суб-URI

Это настройка по умолчанию, рекомендованная Rails, и она также является самой простой. Он работает, монтируя ActionCable.server по определенному пути в вашем config/routes.rb. Таким образом, ваш сервер Action Cable будет работать на том же хосте и порту, что и ваше приложение, но под суб-URI.

Например, ваш routes.rb может содержать:

# Serve websocket cable requests in-process
mount ActionCable.server => '/cable'

(Хотя в комментарии routes.rb говорится, что монтирование ActionCable.server предназначено для обслуживания внутри процесса, Passenger на самом деле настаивает на запуске его как отдельного процесса.)

Чтобы это работало в Passenger + Nginx, вам нужно добавить фрагмент кода на виртуальный хост Nginx. Предположим, что у вас уже есть виртуальный хост для вашего приложения, который выглядит так:

server {
    listen 80;
    server_name www.foo.com;
    root /path-to-your-app/public;
    passenger_enabled on;
}

Вам нужно вставить блок местоположения, который настраивает конечную точку кабеля действия, например:

server {
    listen 80;
    server_name www.foo.com;
    root /path-to-your-app/public;
    passenger_enabled on;

    ### INSERT THIS!!! ###
    location /cable {
        passenger_app_group_name YOUR_APP_NAME_HERE_action_cable;
        passenger_force_max_concurrent_requests_per_process 0;
    }
}

Замените /cable фактическим путем Action Cable, как указано в файле route.rb.

Замените YOUR_APP_NAME_HERE уникальным идентификатором, которого нет больше нигде в файле конфигурации Nginx.

Параметр passenger_force_max_concurrent_requests_per_process настраивает Passenger для оптимальной производительности WebSocket.

person Camden Narzt    schedule 11.09.2017
comment
спасибо @camden, я собираюсь попробовать это для бита кабелей действия, но (возможно, я исказил свою текущую проблему) - когда я исключаю расположение / блок кабеля действия из уравнения, основная проблема все еще остается: доступ к моему приложение только через --domainname.io-- приводит к ошибке HTTP REQUEST ORIGIN (DOMAINNAME.IO) НЕ СООТВЕТСТВУЕТ REQUEST.BASE_URL (IP-АДРЕСУ), всякий раз, когда я выполняю вход в систему, выход из системы, создание, уничтожение - что угодно. - person Shanthanu Varma; 12.09.2017
comment
[я преждевременно нажал клавишу ввода, извините...] так что проблема с этой частью маркера подлинности из-за несоответствия между siik.io и 127.0.0.1:8000 остаются независимо от того, какое исправление добавлено для кабелей действий. Я думаю, что кабели действий — это отдельная проблема, я упомянул об этом, чтобы объяснить, почему я перешел с apache на nginx. Если ваше предложение состояло в том, чтобы запустить пассажира в автономном режиме + apache для запуска кабелей действия, я очень хочу попробовать это. Только, nginx может похвастаться лучшей обработкой или оперативной памяти и процессов. Я хотел бы сначала изучить, как я могу исправить только перенаправления nginx. - person Shanthanu Varma; 12.09.2017

ИСПРАВЛЕНО.

Я не совсем уверен, как это было решено, я все еще пытаюсь понять, почему все работает. По сути, проблема заключалась в том, как поддерживалась конфигурация Passenger + Nginx. - Я полагаю, что это конкретная проблема хозяина сна.

Моя первоначальная конфигурация VPS была выполнена с использованием Apache в качестве http-сервера в соответствии с руководством Дейва Джонса на YouTube. В разделе хостинга домена на панели Dreamhost есть флажок для использования Passenger с приложением ruby, который не был отмечен в соответствии с исходным руководством, которому я следовал. Читая ссылки @Camden - очень полезно - я решил перенастроить все с нуля и проверил этот Passenger Box на панели управления вместе с безопасным битом HTTPS, добавил сертификат от «Let's Encrypt SSL» и перезапустил свой сервер. Все стало работать идеально, как и требовалось. Я также добавил заголовки для порта 443 в блок местоположения для '/cable' в файле CONF и добавил http://www.domainnam.io в файле production.rb, для параметра config.force_ssl установлено значение true.

Итак, в заключение я так понимаю, проблема была в неправильной настройке интеграции пассажирского nginx. Спасибо @Camden за ссылки.

person Shanthanu Varma    schedule 12.09.2017