LoginSignup
1
0

More than 3 years have passed since last update.

【Ruby】ソケットをプロミスキャスモードにする

Last updated at Posted at 2021-02-11

メモ

  • 原理的には以下ページの通りに行う。 setsockopt を呼び出して、その時に PACKET_ADD_MEMBERSHIP オプションとそのオプションに必要な struct packet_mreq のデータを渡せば良い。 Man page of PACKET
  • struct packet_mreqはCの構造体であるが、参考リンクの通り色々と調べたところ、Rubyから渡す場合は構造体のメンバのデータを順番に並べた文字列を渡せば良さそう。
  • 例えば、 mr_ifindex はインターフェース番号(int=4Byte)なので、Rubyの文字列の一文字のデータはCのchar1つに変換されるよう(動作的にそう見えるが厳密には違うかも)なので、インターフェース番号を加えた4文字の文字列を渡せば良い。下記の mr_ifindex メソッドであれば、例えば、インターフェース番号が 1 だったら "1000" が返る。
  • ETH_P_ALL はとりあえず全てのプロトコルを対象とした番号(0x0003)をネットワークバイトオーダーに変換(htons)した値を指定。
  • 実行には root 権限が必要。

サンプルコード

require "socket"

SOL_PACKET = 0x0107 # bits/socket.h
PACKET_ADD_MEMBERSHIP = 0x0001 # netpacket/packet.h
PACKET_MR_PROMISC = 0x0001 # netpacket/packet.h
ETH_P_ALL = 768 # htons(ETH_P_ALL), linux/if_ether.h

# @return [Integer]
def if_name_to_index(if_name)
  Socket.getifaddrs.find do |ifaddr|
     ifaddr.name == if_name
  end&.ifindex
end

# int(4Byte)
#
# @return [String]
def mr_ifindex(if_name)
  [[if_name_to_index(if_name)].pack("c")].pack("a4")
end

# unsigned short(2Byte)
#
# @return [String]
def mr_type
  [PACKET_MR_PROMISC].pack("S")
end

# unsigned short(2Byte)
#
# @return [String]
def mr_alen
  [0].pack("S")
end

# unsigned short(1Byte * 8)
#
# @return [String]
def mr_address
  [0].pack("C")*8
end

# https://linuxjm.osdn.jp/html/LDP_man-pages/man7/packet.7.html
# struct packet_mreq {
#  int            mr_ifindex;    /* インターフェース番号 */ 4Byte
#  unsigned short mr_type;       /* 動作 */ 2Byte
#  unsigned short mr_alen;       /* アドレスの長さ */ 2Byte
#  unsigned char  mr_address[8]; /* 物理層のアドレス */ 1Byte * 8
#};
#
# @return [String]
def mreq(interface)
  mr_ifindex(interface) + mr_type + mr_alen + mr_address
end

mreq = mreq("eth0")

sock = Socket.new(Socket::AF_PACKET, Socket::SOCK_RAW, ETH_P_ALL)
sock.setsockopt(SOL_PACKET, PACKET_ADD_MEMBERSHIP, mreq)

参考

Ruby Raw Socket on Linux (ruby 1.9.3, linux x86_64) https://gist.github.com/k-sone/8036832

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0