我正在尝试在linux中的不同网络接口上的ruby应用程序中打开多个套接字。例如,假设我的接口eth0的IP为192.168.1.2,接口wlan0的IP地址为10.0.0.2。我想在每个接口上同时连接到带有套接字的服务器。我认为绑定到这些接口的IP地址会起作用,但似乎并非如此。在wireshark中,当我绑定到wlan0的IP时,我成功地看到SYN数据包使用正确的源IP发送,但wireshark在eth0上看到它们,并且套接字永远不会打开。
Ruby版本:ruby 1.9.3p194(2012-04-20修订版35410)[x86_64-linux]
这是我目前的代码。我还尝试了针对Socket的ruby-doc页面上记录的Addrinfo方法,结果相同。
require 'socket'
ip = "192.168.1.2" # IP of internal interface
port = 8000
server = "" # IP of the server I'm trying to connect to goes here
lhost = Socket.pack_sockaddr_in(0, ip)
rhost = Socket.pack_sockaddr_in(port, server)
socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
socket.bind(lhost)
socket.connect(rhost)
感谢您的帮助!
答案 0 :(得分:7)
我能够弄明白,并且认为我应该留下我的答案,以防其他人在路上遇到这个问题。
我需要做的是基于源的路由。一般的想法是创建两个路由表,一个强制一个接口上的流量,另一个强制另一个接口上的流量,并且具有使用基于源IP地址的相应路由表的ip规则。我这样设置:
首先,我必须编辑/etc/iproute2/rt_tables
以添加以下行:
128 multiplex0
129 multiplex1
这创建了两个名为128
和129
的路由表,名为multiplex0
和multiplex1
。
接下来,我按如下方式为这些表创建了规则:
ip route add default via 10.0.2.2 table multiplex0
ip route add default via 192.168.1.1 table multiplex1
这些命令指定要在路由表中使用的默认网关。我的10.0 / 16网络的默认网关为10.0.2.2,而我的192.168.1 / 24网络的默认网关为192.168.1.1。
我相信如果您的网络具有相同的默认网关,您可以在上述命令中添加dev eth0
(或任何接口)以指定接口,但我还没有对此进行测试。当我了解更多信息时,我会进行编辑。
编辑:我已对此进行了测试,确实有效。如果在路由中指定接口,则两条路由都可以具有相同的默认网关。
接下来我需要创建规则来使用这些表:
ip rule add from 10.0.0.0/16 table multiplex0
ip rule add from 192.168.1.1/24 table multiplex1
这些规则规定,任何源IP为10.0 / 16范围的数据包都应根据multiplex0中的规则进行路由,而源IP为192.168.1 / 24范围的任何数据包都应使用multiplex1。当数据包使用这些表时,它们被定向到适当的网关和相应的接口。中提琴!
编辑:在此步骤中仅指定网络接口的IP会更准确!例如,如果两个接口都在192.168.1 / 24网络上,那么就有必要。
最后我发布ip route flush cache
以使一切生效并使用上面的ruby代码我能够在正确的接口上打开我的两个套接字到同一个可公开路由的主机。