欺骗 Rails 应用程序认为它位于不同的端口

发布于 2024-10-10 20:33:15 字数 452 浏览 11 评论 0原文

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

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

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

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

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

提前致谢!

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

I have a Rails app that is running on port 8080 that I need to trick to think it's running on port 80.

I am running Varnish on port 80 and forwarding requests to nginx on port 8080, but when the user tries to login with OmniAuth and the Devise gem generates a url to redirect back to the server, it thinks its on port 8080 which then the user will see.

Is there any way to trick the Rails app to hard code the port as 80 (I would think it's a bad practice), or have nginx forward the request as if it's running on port 80?

Since I am not running a nginx proxy to the Rails app I can't think of a way to trick the port.

Has anyone ran into this issue before, if so what sort of configuration is needed to fix it?

Thanks in advance!

EDIT:
Both nginx and Varnish are running on the same server.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

老街孤人 2024-10-17 20:33:16

我在端口 80 上使用 Varnish 进行了相同的设置,在端口 8080 上使用了 nginx,并且 OmniAuth(无 Devise)做了完全相同的事情。我尝试在 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

I have the same setup with Varnish on port 80 and nginx on port 8080 and OmniAuth (no Devise) was doing exactly the same thing. I tried setting X-Forwarded-Port etc in Varnish and fastcgi_param SERVER_PORT 80; in nginx, both without success. The other piece in my setup is Passenger (which you didn't mention) but if you are indeed using Passenger then you can use:

passenger_set_cgi_param SERVER_PORT 80; 

(The docs say you can set this in an http block but that didn't work for me and I had to add it to the server block.)

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

莫言歌 2024-10-17 20:33:16

在 Varnish 中设置X-Forwarded-Port。请参阅此示例以及来自 Google 搜索的其他结果对于“varnish x-forwarded-端口”。

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


标头 X-Forwarded-ForX-Forwarded-ProtoX-Forwarded-Port 是 HTTP 反向代理的一种方式,例如Nginx、Squid 或 Varnish 与“后端”HTTP 应用程序服务器、在 Thin 或 Unicorn 中运行的 Rails 应用程序进行通信,了解用户的实际身份以及用户实际的连接方式。

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

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

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

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

Set up X-Forwarded-Port in Varnish. See this example and the other results from a Google search for "varnish x-forwarded-port".

You must also, of course, set up X-Forwarded-For and X-Forwarded-Proto.


The headers X-Forwarded-For, X-Forwarded-Proto, and X-Forwarded-Port are a way for HTTP reverse proxies such as Nginx, Squid, or Varnish to communicate to the "back-end" HTTP application server, your Rails application running in Thin or Unicorn, who the user actually is and how the user actually connected.

For example, suppose you have Nginx in front of your Rails application. Your Rails application was booted with Thin and is listening on 127.0.0.1:8080, while Nginx is listening on 0.0.0.0:80 for HTTP and 0.0.0.0:443 for HTTPS. Nginx is configured to proxy all connections to the Rails app. Then your Rails app will think that any user's IP address is 127.0.0.1, the port is 8080, and the scheme is http, even if the actual user connected from 1.2.3.4 and requested the page via https on port 443. The solution is to configure Nginx to set the headers:

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

and the Rails app should use these parameters instead of the default ones.

The same applies for whatever reverse proxy you use, such as Varnish in your case.

不羁少年 2024-10-17 20:33:16

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

也许 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>

在 shell 中:

passenger start -e staging -p 3003 -d

You can make a proxy and server it as whatever port you want.

Maybe with apache on top and passenger stand alone...

<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>

In shell:

passenger start -e staging -p 3003 -d
成熟稳重的好男人 2024-10-17 20:33:16

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

正如艾布尔迈克所说; Apache 有一个很棒的模块(mod_proxy),它使用 ProxyPassReverse 将重定向重写回端口 80 重定向。更好的是,使用 mod_proxy_html 它将用端口 80 链接替换 ​​HTML 页面中的端口 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 页面,这将是用清漆完全纠正要困难得多。

Your problem seems you're getting redirects to port 8080. The best solution would be to configure Rails (or the OmniAuth/Devise gem) to treat the requests as if they were fired on port 80 (but I have no idea how or if it is possible).

Like ablemike said; Apache has a great module for this (mod_proxy), with ProxyPassReverse it rewrites the redirects back to port-80 redirects. Better even, with mod_proxy_html it will replace port-8080 links in HTML pages with port-80 links.

If you only need to rewrite redirects, you can rewrite redirects in Varnish VCL with something like:

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");
  }
}

(I think you have to replace obj with beresp if you use varnish >= 2.1)

If you have to rewrite HTML pages, this will be a lot harder to do completely correct with varnish.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文