-
Notifications
You must be signed in to change notification settings - Fork 0
/
mydns_server.rb
executable file
·66 lines (54 loc) · 1.52 KB
/
mydns_server.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#!/usr/bin/env ruby
# info: simple custom dns server, server side script
# it serves ip addresses for the requested names
# platform: all
# depends: none
# requirements: ruby 1.8+
# website: https://github.com/log69/mydns
# copyright: Andras Horvath <mail@log69.com>
# license: GPLv3+
$SAFE = 2
require "socket"
port = 3333
maxip = 1000 # number of maximum ip entries
# listen on socket
s = TCPServer.new port
db = []
loop do
c = s.accept
# get domain name and source ip address
# sanitize input strongly
name = c.gets[/[\?]*[\.\-_a-zA-Z0-9]+/][0..100]
ip = c.addr[-1][/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/]
# question mark makes it a request for name resolution
# command is ?name
if name[0..0] == "?"
i = db.index(name[1..-1])
ip = ""
# send real ip belonging to the name if it exists
ip = db[i+1] if i
# forced wait to block brute force attack on failed lookups
sleep 1 if not i
# send it
# hanlde broken pipe error with recsue for the case
# when the client terminates waiting and so there is no socket
# to send the data to
c.puts ip rescue nil
else
# name exists?
i = db.index(name)
if i
# name already exists, so update the ip,
db[i+1] = ip
else
# name does not exist, so store name and ip,
# secure service from flood and avoid dos attack
# by limiting the number of the entries
# from the same source ip,
db += [name, ip] if db.count(ip) < 10
# secure service from dos attack
# by limiting the number of maximum entries,
db = db[0..maxip*2-1]
end
end
end