【问题标题】:Tricking a Rails App to think it's on a different port欺骗 Rails 应用程序以为它在不同的端口上
【发布时间】:2011-06-03 05:09:28
【问题描述】:

我有一个在端口 8080 上运行的 Rails 应用程序,我需要欺骗它以为它在端口 80 上运行。

我在端口 80 上运行 Varnish 并将请求转发到端口 8080 上的 nginx,但是当用户尝试使用 OmniAuth 登录并且 Devise gem 生成一个 url 以重定向回服务器时,它认为它已开启然后用户将看到的端口 8080。

有什么办法可以欺骗 Rails 应用程序将端口硬编码为 80(我认为这是一种不好的做法),或者让 nginx 转发请求,就好像它在端口 80 上运行一样?

由于我没有为 Rails 应用程序运行 nginx 代理,所以我想不出欺骗端口的方法。

以前有没有人遇到过这个问题,如果有,需要什么样的配置来解决它?

提前致谢!

编辑: nginx 和 Varnish 都运行在同一台服务器上。

【问题讨论】:

    标签: ruby-on-rails nginx port varnish


    【解决方案1】:

    我在端口 80 上使用 Varnish 和在端口 8080 上使用 nginx 进行相同的设置,而 OmniAuth(无设计)正在做同样的事情。我尝试在 Varnish 中设置 X-Forwarded-Port 等,在 nginx 中设置 fastcgi_param SERVER_PORT 80;,均未成功。我设置中的另一部分是Passenger(你没有提到),但如果你确实在使用Passenger,那么你可以使用:

    passenger_set_cgi_param SERVER_PORT 80; 
    

    (文档说您可以将其设置在 http 块中,但这对我不起作用,我必须将其添加到 server 块中。)

    http://modrails.com/documentation/Users%20guide%20Nginx.html#passenger_set_cgi_param

    【讨论】:

    • 2012 年 11 月,18 个月后,这仍然是很好的建议。 FWIW,我还必须把它放在服务器中,而不是 http,nginx 配置的块。
    【解决方案2】:

    在 Varnish 中设置 X-Forwarded-Port。请参阅this example 和 Google 搜索“varnish x-forwarded-port”的其他结果。

    当然,您还必须设置X-Forwarded-ForX-Forwarded-Proto


    标头 X-Forwarded-ForX-Forwarded-ProtoX-Forwarded-Port 是 HTTP 反向代理(例如 Nginx、Squid 或 Varnish)与“后端”HTTP 应用程序服务器通信的一种方式,您的 Rails 应用程序在瘦或独角兽,用户实际是谁以及用户实际连接的方式。

    例如,假设您的 Rails 应用程序前面有 Nginx。您的 Rails 应用程序是使用 Thin 启动的,并且正在侦听 127.0.0.1:8080,而 Nginx 正在侦听 HTTP 的 0.0.0.0:80 和 HTTPS 的 0.0.0.0:443。 Nginx 被配置为代理到 Rails 应用程序的所有连接。那么你的 Rails 应用会认为任何用户的 IP 地址是127.0.0.1,端口是8080,scheme 是http,即使实际用户从1.2.3.4 连接并通过https 请求页面端口443。解决方法是配置Nginx设置headers:

    X-Forwarded-For: 1.2.3.4
    X-Forwarded-Scheme: https
    X-Forwarded-Port: 443
    

    Rails 应用应该使用这些参数而不是默认参数。

    这同样适用于您使用的任何反向代理,例如您使用的 Varnish。

    【讨论】:

    • 这不是一个描述性很强的答案。我需要在 nginx 或 Varnish 中设置 X-Forwarded-For 和 X-Forwarded-Proto 吗?我还在端口 80 上监听 Varnish 吗?
    • 我已经用更多描述更新了我的答案,希望能让X-Forwarded-For系统清晰。
    • 这个答案很受欢迎。这帮助我解决了 ELB -> Nginx -> Unicorn(rails) 配置中 OAuth2 回调失败的谜团
    【解决方案3】:

    您可以创建一个代理服务器并将其作为您想要的任何端口。

    也许上面有 apache,乘客独立......

    <VirtualHost *:80>
     ServerName <name>
     DocumentRoot /home/deploy/<name>
    
     PassengerEnabled off
     ProxyPass / http://127.0.0.1:<port>/
     ProxyPassReverse / http://127.0.0.1:<port>/
    
    </VirtualHost>
    

    在外壳中:

    passenger start -e staging -p 3003 -d
    

    【讨论】:

    • 我正在使用 nginx,但我没有将其作为独立实例运行。
    • 如果您打算在标准部署模型之外做事,请不要坚持这个理想。
    【解决方案4】:

    您的问题似乎是重定向到端口 8080。最好的解决方案是配置 Rails(或 OmniAuth/Devise gem)以将请求视为在端口 80 上触发(但我不知道如何或者如果可能的话)。

    就像ablemike所说的那样; Apache 有一个很棒的模块(mod_proxy),它使用 ProxyPassReverse 将重定向重写回端口 80 重定向。更好的是,使用 mod_proxy_html 它将用 port-80 链接替换 ​​HTML 页面中的 port-8080 链接。

    如果你只需要重写重定向,你可以在 Varnish VCL 中重写重定向:

    sub vcl_fetch {
    
      ...
    
      #Rewrite redirect from port 8080 to port 80
      if ( obj.http.Location ~ "^http://[^:]+:8080/.*" ) {
        set obj.http.Location = regsub(obj.http.Location, ""^(http://[^:]+):8080(/.*)","\1\2");
      }
    }
    

    (如果你使用 varnish >= 2.1,我认为你必须用 beresp 替换 obj)

    如果您必须重写 HTML 页面,使用 varnish 完全正确地做到这一点会困难得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多