Skip to content

Instantly share code, notes, and snippets.

@kubo39
Last active December 13, 2015 23:39
Show Gist options
  • Save kubo39/4993433 to your computer and use it in GitHub Desktop.
Save kubo39/4993433 to your computer and use it in GitHub Desktop.
fake DNS server
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
require 'socket'
class DNSQuery
attr_reader :domain_io
def initialize data
@data = data
@domain_io = ''
tipo = data[2].ord >> 3 & 15 # Opcode bits
if tipo == 0 # Standard query
ini = 12
lon = data[ini].ord
while lon != 0
@domain_io = data[(ini+1)...(ini+lon+1)] + '.'
ini += lon + 1
lon = data[ini].ord
end
end
end
def response ip
packet = ''
unless @domain_io.empty?
packet += @data[0..1] + "\x81\x80"
packet += self.data[4..5] + self.data[4..5] + '\x00\x00\x00\x00' # Questions and Answers Counts
packet += self.data[12..-1] # Original Domain Name Question
packet += '\xc0\x0c' # Pointer to domain name
packet += '\x00\x01\x00\x01\x00\x00\x00\x3c\x00\x04' # Response type, ttl and resource data length -> 4 bytes
packet += ip.split('.').map{|x| x.to_i.to_chr }.join # 4bytes of IP
end
packet
end
end
if __FILE__ == $0
ip = '192.168.1.1'
puts "minifakeDNS :: dom.query. 60 IN A #{ip}"
udps = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
sockaddr = Socket::sockaddr_in(53, "localhost")
udps.bind(sockaddr)
begin
while true
data, sockaddr = udps.recvfrom(1024)
q = DNSQuery.new(data)
udps.send(q.response(ip), 0, sockaddr)
puts 'Response: #{q.domain_io} -> #{ip}'
end
rescue KeyboardInterrupt
puts "finish"
ensure
udps.close
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment