古いプログラムなので、もう少し手入れをしたいけど、とりあえず修正版公開します。Ruby 1.9あたり以降なRubyが入っているLinuxで多分動くよ!Raspberry Piで動作確認済み。root権限で動かしてね!使用例
ruby modoki.rb google.com
綺麗になったらgithubに上げます(多分)
modoki.rb
require 'socket' require './ip' require './udp' require './icmp' def make_ip_header(src_ip, dst_ip, iplen) ip = IPHeader.new ip.version = 4 ip.ip_tos = 0 ip.ip_hl = 5 ip.ip_id = 0 ip.ip_len = iplen ip.ip_off = 0 ip.ip_ttl = 64 ip.ip_p = Socket::IPPROTO_UDP ip.ip_src = src_ip ip.ip_dst = dst_ip ip.ip_sum = 0 return ip.to_byte_array() end def make_udp_header udp = UDPHeader.new udp.uh_sport = 33434 udp.uh_dport = 33434 udp.uh_ulen = 8 udp.uh_sum = 0 return udp.to_byte_array end if ARGV.size() < 1 puts 'usage ruby modoki.rb dst_ip' exit(1) end send_sa = Socket.sockaddr_in(0, ARGV[0]) send_sd = Socket.open(Socket::AF_INET, Socket::SOCK_RAW, 255) recv_sd = Socket.open(Socket::AF_INET, Socket::SOCK_RAW, Socket::IPPROTO_ICMP) recv_sa = Socket.sockaddr_in(0, "0.0.0.0") host = Socket.gethostbyname(ARGV[0])[3] ip_addr = sprintf("%d.%d.%d.%d", host[0].unpack('C')[0], host[1].unpack('C')[0], host[2].unpack('C')[0], host[3].unpack('C')[0]) packet = make_ip_header("0.0.0.0", ip_addr, 28) packet << make_udp_header() puts "scanroute #{ip_addr}" for ttl in 1..64 print ttl packet[8] = [ttl & 0xFF].pack('C') i = 0 ip_header = nil icmp = nil for i in 0..3 if i == 3 puts break end break_flag = false send_sd.send(packet, 0, send_sa) while true ret = IO::select([recv_sd], nil, nil, 1.0) if ret == nil || ret[0].size() == 0 print ' ?' break end buff, sockaddr = recv_sd.recvfrom(8192) ip_header = IPHeader.new(buff) buff.slice!(0..(ip_header.ip_hl << 2) - 1) icmp = ICMP.new(buff) if((icmp.icmp_type == ICMP::TIMXCEED && icmp.icmp_code == ICMP::TIMXCEED_INTRANS) || icmp.icmp_type == ICMP::UNREACH) break_flag = true break end end if break_flag break end end if(i < 3) puts " #{ip_header.ip_src}" if(icmp.icmp_type == ICMP::UNREACH) if(icmp.icmp_code == ICMP::UNREACH_PORT) puts "Reach!" elsif(icmp.icmp_code == ICMP::UNREACH_HOST) puts "Host Unreachable" elsif(icmp.icmp_code == ICMP::UNREACH_NET) puts "Network Unreachable" end break end end end send_sd.close() recv_sd.close()
ip.rb
class IPHeader attr_accessor :version attr_accessor :ip_hl attr_accessor :ip_tos attr_accessor :ip_len attr_accessor :ip_id attr_accessor :ip_off attr_accessor :ip_ttl attr_accessor :ip_p attr_accessor :ip_sum attr_accessor :ip_src attr_accessor :ip_dst def initialize(packet = nil) if(packet == nil) return end @version = (packet[0].unpack('C')[0] >> 4) & 0x0F @ip_hl = packet[0].unpack('C')[0] & 0x0F @ip_tos = packet[1].unpack('C')[0] @ip_len = packet[2, 2].unpack('n')[0] @ip_id = packet[4, 2].unpack('n')[0] @ip_off = packet[6].unpack('n')[0] @ip_ttl = packet[8].unpack('C')[0] @ip_p = packet[9].unpack('C')[0] @ip_sum = packet[10].unpack('n')[0] @ip_src = ip_to_s(packet, 12) @ip_dst = ip_to_s(packet, 16) end def to_byte_array() array = " " array[0] = [((@version << 4) + @ip_hl) & 0xFF].pack('C') array[1] = [@ip_tos & 0xFF].pack('C') array[2] = [(@ip_len >> 8) & 0xFF].pack('C') array[3] = [@ip_len & 0xFF].pack('C'); array[4] = [(@ip_id >> 8) & 0xFF].pack('C') array[5] = [@ip_id & 0xFF].pack('C') array[6] = [(@ip_off >> 8) & 0xFF].pack('C') array[7] = [@ip_off & 0xFF].pack('C') array[8] = [@ip_ttl & 0xFF].pack('C') array[9] = [@ip_p & 0xFF].pack('C') array[10] = [(@ip_sum >> 8) & 0xFF].pack('C') array[11] = [@ip_sum & 0xFF].pack('C') s_to_ip(array, 12, @ip_src) s_to_ip(array, 16, @ip_dst) return array end def s_to_ip(array, index, str_ip) split = str_ip.split('.') for i in 0..3 array[index + i] = [split[i].to_i() & 0xFF].pack('C') end end def ip_to_s(packet, index) return sprintf("%d.%d.%d.%d", packet[index].unpack('C')[0], packet[index + 1].unpack('C')[0], packet[index + 2].unpack('C')[0], packet[index + 3].unpack('C')[0]) end end
udp.rb
class UDPHeader attr_accessor :uh_sport attr_accessor :uh_dport attr_accessor :uh_ulen attr_accessor :uh_sum def initialize(packet = nil) if(packet == nil) return end # @uh_sport = (packet[0] << 8) + packet[1] # @uh_dport = (packet[2] << 8) + packet[3] # @uh_ulen = (packet[4] << 8) + packet[5] # @uh_sum = (packet[6] << 8) + packet[7] end def to_byte_array() array = " " array[0] = [(@uh_sport >> 8) & 0xFF].pack('C') array[1] = [@uh_sport & 0xFF].pack('C') array[2] = [(@uh_dport >> 8) & 0xFF].pack('C') array[3] = [@uh_dport & 0xFF].pack('C') array[4] = [(@uh_ulen >> 8) & 0xFF].pack('C') array[5] = [@uh_ulen & 0xFF].pack('C') array[6] = [(@uh_sum >> 8) & 0xFF].pack('C') array[7] = [@uh_sum & 0xFF].pack('C') return array end end
icmp.rb
class ICMP attr_reader :icmp_type attr_reader :icmp_code attr_reader :icmp_cksum ECHOREPLY = 0 UNREACH = 3 SOURCEQUENCH = 4 REDIRECT = 5 ECHO = 8 ROUTERADVERT = 9 ROUTERSOLICIT = 10 TIMXCEED = 11 PARAMPROB = 12 TSTAMP = 13 TSTAMPREPLY = 14 IREQ = 15 IREQREPLY = 16 MASKREQ = 17 MASKREPLY = 18 UNREACH_NET = 0 UNREACH_HOST = 1 UNREACH_PROTOCOL = 2 UNREACH_PORT = 3 UNREACH_NEEDFRAG = 4 UNREACH_SRCFAIL = 5 UNREACH_NET_UNKNOWN = 6 UNREACH_HOST_UNKNOWN = 7 UNREACH_ISOLATED = 8 UNREACH_NET_PROHIB = 9 UNREACH_HOST_PROHIB = 10 UNREACH_TOSNET = 11 UNREACH_TOSHOST = 12 UNREACH_FILTER_PROHIB = 13 UNREACH_HOST_PRECEDENCE = 14 REDIRECT_NET = 0 REDIRECT_HOST = 1 REDIRECT_TOSNET = 2 REDIRECT_TOSHOST = 3 TIMXCEED_INTRANS = 0 TIMXCEED_REASS = 1 PARAMPROB_ERRATPTR = 0 PARAMPROB_OPTABSENT = 1 PARAMPROB_LENGTH = 2 def initialize(packet) @icmp_type = packet[0].unpack('C')[0] @icmp_code = packet[1].unpack('C')[0] @icmp_cksum = packet[2..3].unpack('n')[0] end end
参考書!
基礎からわかるTCP/IP ネットワーク実験プログラミング―Linux/FreeBSD対応
- 作者: 村山公保
- 出版社/メーカー: オーム社
- 発売日: 2004/10
- メディア: 単行本
- 購入: 4人 クリック: 43回
- この商品を含むブログ (13件) を見る