F
Filipe Manana
Hello,
I am trying to use, through 100% Ruby code, Linux Raw Sockets for packet
sniffing. I am using the same syscalls that I would use in C code. I am
able to inject packets through the raw socket but not to sniff packets.
Here's my Ruby code:
class RawSocket
PF_PACKET = 17 # linux/socket.h
AF_PACKET = PF_PACKET # linux/socket.h
ETH_P_ALL = 0x00_03 # linux/if_ether.h
ETH_P_IP = 0x08_00 # linux/if_ether.h
SIOCGIFINDEX = 0x89_33 # bits/ioctls.h
SIZEOF_INT = ([0].pack 'I').length
def initialize(interface)
@interface = interface
@sock = nil
begin
@sock = Socket.new(PF_PACKET, Socket::SOCK_RAW,
Utils.htons(ETH_P_ALL))
# struct ifreq in net/if.h
ifreq = [@interface].pack 'a16'
ifreq << ( [""].pack 'a16' )
@sock.ioctl(SIOCGIFINDEX, ifreq)
# struct sockaddr_ll in linux/if_packet.h
sll = [AF_PACKET].pack 'S' # sll_family
sll << ( [ETH_P_ALL].pack 'S' ) # sll_protocol
sll << ifreq[16 .. (16 + SIZEOF_INT)] # sll_ifindex
sll << ( [0].pack 'S' ) # sll_hatype
sll << ( [0].pack 'C' ) # sll_pkttype
sll << ( [0].pack 'C' ) # sll_halen
sll << ( ([0].pack 'C') * 8 ) # sll_addr[8]
@sock.bind sll
rescue Exception => ex
@sock.close if @sock
STDERR.puts "Error creating raw socket: #{ex.message}\n"
end
def send(packet_bytes)
cnt = -1
begin
cnt = @sock.write packet_bytes
@sock.flush
rescue Exception => ex
STDERR.puts "RawSocket send failed: #{ex.message}\n"
end
sent = false
if cnt == -1
STDERR.puts "RawSocket send returned -1.\n"
elsif cnt < bytes.length
msg << "RawSocket sent only #{cnt} bytes out of
#{packet_bytes.length}.\n"
STDERR.puts msg
else
sent = true
end
sent
end
def receive
data = nil
begin
data = (@sock.recvfrom 2048))[0]
#data = @sock.read
rescue Exception => ex
STDERR.puts "RawSockt receive failed: #{ex.class.name} |
#{ex.message}\n"
end
data
end
end
Unfortunately the "recvfrom" method never returns. Same happens using
the "read" method from the superclass IO.
Any suggestions?
Thanks
I am trying to use, through 100% Ruby code, Linux Raw Sockets for packet
sniffing. I am using the same syscalls that I would use in C code. I am
able to inject packets through the raw socket but not to sniff packets.
Here's my Ruby code:
class RawSocket
PF_PACKET = 17 # linux/socket.h
AF_PACKET = PF_PACKET # linux/socket.h
ETH_P_ALL = 0x00_03 # linux/if_ether.h
ETH_P_IP = 0x08_00 # linux/if_ether.h
SIOCGIFINDEX = 0x89_33 # bits/ioctls.h
SIZEOF_INT = ([0].pack 'I').length
def initialize(interface)
@interface = interface
@sock = nil
begin
@sock = Socket.new(PF_PACKET, Socket::SOCK_RAW,
Utils.htons(ETH_P_ALL))
# struct ifreq in net/if.h
ifreq = [@interface].pack 'a16'
ifreq << ( [""].pack 'a16' )
@sock.ioctl(SIOCGIFINDEX, ifreq)
# struct sockaddr_ll in linux/if_packet.h
sll = [AF_PACKET].pack 'S' # sll_family
sll << ( [ETH_P_ALL].pack 'S' ) # sll_protocol
sll << ifreq[16 .. (16 + SIZEOF_INT)] # sll_ifindex
sll << ( [0].pack 'S' ) # sll_hatype
sll << ( [0].pack 'C' ) # sll_pkttype
sll << ( [0].pack 'C' ) # sll_halen
sll << ( ([0].pack 'C') * 8 ) # sll_addr[8]
@sock.bind sll
rescue Exception => ex
@sock.close if @sock
STDERR.puts "Error creating raw socket: #{ex.message}\n"
end
def send(packet_bytes)
cnt = -1
begin
cnt = @sock.write packet_bytes
@sock.flush
rescue Exception => ex
STDERR.puts "RawSocket send failed: #{ex.message}\n"
end
sent = false
if cnt == -1
STDERR.puts "RawSocket send returned -1.\n"
elsif cnt < bytes.length
msg << "RawSocket sent only #{cnt} bytes out of
#{packet_bytes.length}.\n"
STDERR.puts msg
else
sent = true
end
sent
end
def receive
data = nil
begin
data = (@sock.recvfrom 2048))[0]
#data = @sock.read
rescue Exception => ex
STDERR.puts "RawSockt receive failed: #{ex.class.name} |
#{ex.message}\n"
end
data
end
end
Unfortunately the "recvfrom" method never returns. Same happens using
the "read" method from the superclass IO.
Any suggestions?
Thanks