【问题标题】:Outgoing ports for making HTTP requests from Ruby on Rails app用于从 Ruby on Rails 应用程序发出 HTTP 请求的传出端口
【发布时间】:2018-08-14 08:10:58
【问题描述】:

我的应用程序(使用 jRuby 的 Ruby on Rails、在 puma 上、在 CentOS 6 上的 nginx 上)想要向远程 REST API 服务发出直接的服务器到服务器请求。 我的应用程序与服务网络位于不同的网络中,这意味着 IT 部门必须配置防火墙以允许这些请求。

他们想知道

  • 源(IP 和端口)和
  • 目标(IP 和端口)

除了源端口,一切都很简单。甚至可以让我的应用程序只使用一个端口吗?如果没有,我至少可以给出一个端口范围吗?这是如何配置的?

【问题讨论】:

  • 在通过某些客户端向外部服务发出请求时,ruby(或通常任何 tcp 客户端)将创建一个套接字并从dynamic range (49152-65535) 分配端口。您可能应该将它们作为源端口列入白名单。

标签: ruby-on-rails ruby http httparty


【解决方案1】:

解决方案

我刚刚看到,您可以使用:local_port:local_host 请求选项:

显然,如果要指定 local_port,则必须指定 local_host,这是一直到 Socket 和事件 connect(2) 的限制

# Get the first local IP address which is not the loopback
# There are far better way of doing this, this is just for the example
addr = Socket.ip_address_list.select(&:ipv4?).detect{|addr| addr.ip_address != '127.0.0.1'}

# Start a connection using a predefined port
HTTParty.get 'http://google.com', local_port: 60000, local_host: addr.ip_address

如果要覆盖本地端口,我们必须同时指定 local_host 和 local_port 的原因是 Socket 使用Addrinfo.getaddrinfo,如果只指定端口,它会返回环回地址。

这是由于getaddrinfo(3):

如果在hints.ai_flags 中未设置AI_PASSIVE 标志,则返回的套接字地址将适合与connect(2)、sendto(2) 或sendmsg(2) 一起使用。如果 node 为 NULL,则网络地址将设置为环回接口地址(INADDR_LOOPBACK 用于 IPv4 地址,IN6ADDR_LOOPBACK_INIT 用于 IPv6 地址);这由打算与在同一主机上运行的对等方通信的应用程序使用。

并且在这种情况下没有设置 AI_PASSIVE,因为我们不想设置bind,而是设置connect

使用环回地址,外部网络因此无法访问,这也是我们需要指定 local_host 的原因。


原答案

您可以通过首先创建Net::HTTP 实例然后配置local_port(一个R/W 属性)然后开始连接来做到这一点。

如果您使用任何其他方式建立连接,您可能需要查看文档以查看是否有此类方法可用。

http = Net::HTTP.new(address, port)
http.local_port = 666
http.local_host = 'your ip address'
http.start do
  # whatever
end

local_port 是一个attr_accessor@local_port 直接用于打开 TCP 套接字:TCPSocket.open(conn_address, conn_port, @local_host, @local_port)

【讨论】:

  • 谢谢,知道了。现在有趣的是HTTParty.get 'http://google.com' 工作正常,但HTTParty.get 'http://google.com', local_port: 60000(或任何其他有效端口)产生“Errno::EHOSTUNREACH: 无法打开到 google.com:80 的 TCP 连接(没有到主机的路由 - connect(2) for "google .com" 端口 80)"
  • 也许您根本无法使用端口 60000?
  • 对于 forbidden 端口(例如 10)我收到一个明确的禁止错误“Errno::EACCES: 无法打开与 google.com:80 的 TCP 连接(权限被拒绝) - bind(2) for nil port 10)" vs. 上面的错误。
  • @AlexanderPresber 我不是在谈论禁止端口,但无论如何错误不是我想的。我仍在寻找为什么它不起作用的确切原因,但同时我用解决方案更新了我的答案,你也必须提供 local_host ;-)
猜你喜欢
  • 2011-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多