我目前正在尝试用Ruby写一些东西,它将通过原始套接字发送数据。部分原因可能是由于对套接字的理解有点不稳定,但我觉得资源几乎没有 - 但并非完全存在。
特别是,我试图转换以下Python代码(如果它有帮助):
#!/usr/bin/env python
from socket import socket, AF_PACKET, SOCK_RAW
s = socket(AF_PACKET, SOCK_RAW)
s.bind(("lo", 0))
geonet_frame = "\x00\x1f\xc6\x51\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\xc6
\x51\x07\x07\x07\x07\x07\x07\xef\x06\x07\x35\x97\x00\x24\x8c\x7a\xdf\x6f\x08
\x00\x45\x00\x00\x3d\xf3\x7f\x40\x00\x40\x11\x30\xc6\x0a\x01\x01\x68\x0a\x01
\x01\x01\x99\x80\x00\x35\x00\x29\x16\xa5\x01\x76\x01\x00\x00\xff\x00\x00\x01
\x00\x00\x00"
s.send(geonet_frame)
在搜索问题时,我最常看到的结果是this Stack Overflow question,它不会直接提供任何可行的代码示例,而this explanation似乎比我需要的更多,而且看起来似乎也是如此包含我无法访问的文件。
我已经尝试了documentation for the Socket class中列出的一些内容,但即使我能够使其工作,我也似乎无法达到相同的效果。例如,我可能会尝试:
soc = Socket.open(Socket::PF_INET, Socket::SOCK_RAW, Socket::IPPROTO_RAW)
soc.send(mypacket, 0, Socket.pack_sockaddr_in(0, "127.0.0.1"))
...虽然它将完成,但它不会产生所需的结果(在这种情况下,它不会在TCPDump上创建DOS,如here所示,而等效的Python代码会)。
Ruby中的这个比我期待的更复杂吗?或者我只是缺少一些可以让我这样做的神奇功能组合?
更新:这是捕获所需数据包的图片。
答案 0 :(得分:3)
这样做:
require 'socket'
interface = 'lo' # loopback interface
interface_index = 0x8933 # SIOCGIFINDEX
geonet_frame = "\x00\x1f\xc6\x51\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\xc6\x51\x07\x07\x07\x07\x07\x07\xef\x06\x07\x35\x97\x00\x24\x8c\x7a\xdf\x6f\x08\x00\x45\x00\x00\x3d\xf3\x7f\x40\x00\x40\x11\x30\xc6\x0a\x01\x01\x68\x0a\x01\x01\x01\x99\x80\x00\x35\x00\x29\x16\xa5\x01\x76\x01\x00\x00\xff\x00\x00\x01\x00\x00\x00"
socket = Socket.new(Socket::AF_PACKET, Socket::SOCK_RAW, Socket::IPPROTO_RAW)
ifreq = [interface.dup].pack 'a32'
socket.ioctl(interface_index, ifreq)
socket.bind([Socket::AF_PACKET].pack('s') + [Socket::IPPROTO_RAW].pack('n') + ifreq[16..20]+ ("\x00" * 12))
socket.send(geonet_frame, 0)
我使用了AF_PACKET
,因为它与python示例匹配,但如果您的系统不支持,则可以将其替换为PF_PACKET
。
以Cocoabean建议替换geonet_frame
变量也有效:
geonet_frame = [ 0x00, 0x1f, 0xc6, 0x51, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xc6, 0x51, 0x07, 0x07, 0x07, 0x07,0x07, 0x07, 0xef, 0x06, 0x07, 0x35, 0x97, 0x00, 0x24, 0x8c, 0x7a, 0xdf, 0x6f, 0x08, 0x00, 0x45, 0x00, 0x00, 0x3d, 0xf3, 0x7f, 0x40, 0x00, 0x40, 0x11, 0x30, 0xc6, 0x0a, 0x01, 0x01, 0x68, 0x0a, 0x01, 0x01, 0x01, 0x99, 0x80, 0x00, 0x35, 0x00, 0x29, 0x16, 0xa5, 0x01, 0x76, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00].pack("C*")
在CentOS 6.6上使用ruby 1.9.3p484进行测试。希望它有所帮助。
干杯。
答案 1 :(得分:0)
我认为你创建套接字是正确的,你只是以错误的格式发送数据。 Python看到一系列字节,而ruby看到一串字符。 pack
方法将从字节数组中创建一个String。
http://www.ruby-doc.org/core-2.1.5/Array.html#method-i-pack
尝试将此作为示例尝试中mypacket
的值:
mypacket = [ 0x00, 0x1f, 0xc6, 0x51, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xc6, 0x51, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0xef, 0x06, 0x07, 0x35, 0x97,
0x00, 0x24, 0x8c, 0x7a, 0xdf, 0x6f, 0x08, 0x00, 0x45, 0x00,
0x00, 0x3d, 0xf3, 0x7f, 0x40, 0x00, 0x40, 0x11, 0x30, 0xc6,
0x0a, 0x01, 0x01, 0x68, 0x0a, 0x01, 0x01, 0x01, 0x99, 0x80,
0x00, 0x35, 0x00, 0x29, 0x16, 0xa5, 0x01, 0x76, 0x01, 0x00,
0x00, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00].pack("C*")
simplest way to send raw Byte-arrays using Ruby's TCPSocket-Class