Пассажир 2.2.4, nginx 0.7.61 и SSL

Пассажир 2.2.4, nginx 0.7.61 и SSL

Удалось ли кому-нибудь настроить Passenger и nginx с SSL? Я потратил часы, пытаясь заставить эту конфигурацию работать так, как мне хотелось бы, используя те немногие ресурсы, которые есть в сети, и я не могу заставить ни один из предположительно пересылаемых заголовков отображаться в контроллере Rails.

Например, с помощью следующего файла конфигурации (и нескольких его вариаций):

server {
    listen 3000;
    server_name .example.com;
    root /Users/website/public;
    passenger_enabled on;
    rails_env development;
}

server {
    listen 3443;
    root /Users/website/public;
    rails_env development;
    passenger_enabled on;

    ssl                  on;
    #ssl_verify_client    on;                                               
    ssl_certificate      /Users/website/ssl/server.crt;
    ssl_certificate_key  /Users/website/ssl/server.key;
    #ssl_client_certificate /Users/website/ssl/CA.crt;                                                                              
    ssl_session_timeout  5m;

    ssl_protocols  SSLv3 TLSv1;
    ssl_ciphers  ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP;

    proxy_set_header         Host             $http_host;
    proxy_set_header         X-Real-IP        $remote_addr;
    proxy_set_header         X_FORWARDED_PROTO https;
    proxy_set_header         X-Forwarded-For  $proxy_add_x_forwarded_for;
    #proxy_set_header        X-SSL-Subject    $ssl_client_s_dn;             
    #proxy_set_header        X-SSL-Issuer     $ssl_client_i_dn;             
    proxy_redirect           off;
    proxy_max_temp_file_size 0;
}

и код Rails в контроллере, например, такой:

request.headers.each { |k, v|
  RAILS_DEFAULT_LOGGER.error "Header #{k} Val #{v}"
}

появляются другие заголовки, но не те, которые установлены в nginx, например:

Header rack.multithread Val false
Header REQUEST_URI Val /login/new
Header REMOTE_PORT Val 64021
Header rack.multiprocess Val true
Header PASSENGER_USE_GLOBAL_QUEUE Val false
Header PASSENGER_APP_TYPE Val rails
Header SCGI Val 1
Header SERVER_PORT Val 3443
Header HTTP_ACCEPT_CHARSET Val ISO-8859-1,utf-8;q=0.7,*;q=0.7
Header rack.request.query_hash Val 
Header DOCUMENT_ROOT Val /Users/website/public

Я даже зашел так далеко, что изменил метод Passenger abstract_request_handler, main_loopт.е.

headers, input = parse_request(client)
if headers
  if headers[REQUEST_METHOD] == PING
    process_ping(headers, input, client)
  else
    headers.each { |h,v|
      log.unknown "abstract_request_handler: #{h} = #{v}"
    }
    process_request(headers, input, client)
  end
end

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

abstract_request_handler: HTTP_KEEP_ALIVE = 300
abstract_request_handler: HTTP_USER_AGENT = Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1) Gecko/20090624 Firefox/3.5
abstract_request_handler: PASSENGER_SPAWN_METHOD = smart-lv2
abstract_request_handler: CONTENT_LENGTH = 0
abstract_request_handler: HTTP_IF_NONE_MATCH = "b6e8b9afbc1110ee3bf0c87e119252ad"
abstract_request_handler: HTTP_ACCEPT_LANGUAGE = en-us,en;q=0.5
abstract_request_handler: SERVER_PROTOCOL = HTTP/1.1
abstract_request_handler: HTTPS = on
abstract_request_handler: REMOTE_ADDR = 127.0.0.1
abstract_request_handler: SERVER_SOFTWARE = nginx/0.7.61
abstract_request_handler: SERVER_ADDR = 127.0.0.1
abstract_request_handler: SCRIPT_NAME = 
abstract_request_handler: PASSENGER_ENVIRONMENT = development
abstract_request_handler: REMOTE_PORT = 64021
abstract_request_handler: REQUEST_URI = /login/new
abstract_request_handler: HTTP_ACCEPT_CHARSET = ISO-8859-1,utf-8;q=0.7,*;q=0.7
abstract_request_handler: SERVER_PORT = 3443
abstract_request_handler: SCGI = 1 
abstract_request_handler: PASSENGER_APP_TYPE = rails
abstract_request_handler: PASSENGER_USE_GLOBAL_QUEUE = false

Я устал биться головой об стену, поэтому буду очень признателен за любую помощь!

решение1

Пассажир 3 реализует эту функцию с помощью новой директивы, passenger_set_cgi_paramкоторая ведет себя как proxy_set_header.

Например, чтобы передать переменные SSL в Rack, можно сделать следующее:

server {
  listen 443 default ssl;

  # other SSL stuff goes here
  # other passenger stuff here

  passenger_set_cgi_param  X_FORWARDED_PROTO       https;
  passenger_set_cgi_param  X-SSL-Raw-Cert          $ssl_client_raw_cert;
  passenger_set_cgi_param  X-SSL-Cert              $ssl_client_cert;
  passenger_set_cgi_param  X-SSL-Client-S-DN       $ssl_client_s_dn;
  passenger_set_cgi_param  X-SSL-Client-I-DN       $ssl_client_i_dn;
  passenger_set_cgi_param  X-SSL-Client-Verify     $ssl_client_verify;
}

После этого у вас будет доступ к X-SSL-Raw-Certи другим заголовкам в Rack::Requestэкземпляре (доступным из #requestвашего контроллера).

Пока это не документировано, но вот дополнительная информация:

решение2

Passenger — это не то же самое, что проксирование, он использует SCGI в некотором роде. Единственный способ обойти это — проксировать обратно через nginx на другом (защищенном) порту. Это далеко не идеально, но работает.

решение3

Хм... У вас случайно нет директивы location, где proxy_set_header используется еще раз?

Я спрашиваю, потому что директивы массива, такие как fastcgi или proxy_set_header, не наследуются от более высокого уровня, когда они изменяются на более низком уровне. Поскольку вы объявляете свой proxy_set_header на уровне сервера, любая другая директива proxy_set_header на более низком уровне, например, "location", очистит все объявленное до сих пор для этого уровня, кроме вашей последней директивы.

решение4

Допустимые параметры для nginx/1.8.1 Phusion_Passenger/5.0.25

passenger_enabled on; passenger_set_header X-SSL-Subject $ssl_client_s_dn; passenger_set_header X-Client-DN $ssl_client_s_dn; passenger_set_header X-Client-Verify $ssl_client_verify; passenger_set_header X-Forwarded-For "";

Связанный контент