Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local DNS_PORT = 65535
- local VERSION = "1.0"
- local computer = require("computer")
- local component = require("component")
- local event = require("event")
- local thread = require("thread")
- local ser = require("serialization")
- local term = require("term")
- local io = require("io")
- local filesystem = require("filesystem")
- local modem = component.modem
- local data = component.data
- local secureConnections = {}
- local attempts = {}
- local logFile = io.open("/home/dnslogs.log","w")
- local function strip(str)
- while (string.byte(str, string.len(str)) == 10 or string.byte(str, string.len(str)) == 13) do
- str = string.gsub(str, "\n", "")
- str = string.gsub(str, "\r", "")
- end
- return str
- end
- local function exists(path)
- local f=io.open(path,"r")
- if f~=nil then io.close(f) return true else return false end
- end
- local function log(log)
- local msg = "[" .. os.date("%c") .. "]" .. log
- print(msg)
- logFile:write(msg .. "\n")
- logFile:flush()
- end
- local function DNS(domain)
- local path = "/home/domains/" .. domain .. ".domain"
- if exists(path) then
- l = io.lines(path)
- return l(), l()
- end
- end
- local function getPass()
- local path = "/home/password.pass"
- if exists(path) then
- return io.open(path, "r"):read("*a")
- end
- end
- local function deleteDomain(domain)
- local path = "/home/domains/" .. domain .. ".domain"
- if exists(path) then
- os.remove(path)
- return true
- else
- return false
- end
- end
- local function createDomain(domain, address, owner)
- local path = "/home/domains/" .. domain .. ".domain"
- if not exists(path) then
- local f = io.open(path, "w")
- f:write(address .. "\n" .. owner)
- f:close()
- return true
- else
- return false
- end
- end
- local function checkPassword(addr, password)
- local key = secureConnections[addr]
- if key then
- if type(password.Password) == "string" and type(password.IV) == "string" then
- if not attempts[addr] then
- attempts[addr] = {NextTry = 0, TriesLeft = 2}
- end
- if computer.uptime() >= attempts[addr].NextTry then
- local decPass = data.decrypt(password.Password, key, password.IV)
- if data.sha256(decPass) == getPass() then
- attempts[addr].TriesLeft = 2
- return true
- else
- if attempts[addr].TriesLeft > 0 then
- attempts[addr].TriesLeft = attempts[addr].TriesLeft - 1
- else
- attempts[addr].NextTry = computer.uptime() + 600
- end
- return false, 25, "Bad password"
- end
- else
- return false, 24, "Blocked by filter"
- end
- else
- return false, 22, "Bad password structure"
- end
- else
- return false, 21, "Encryption key not registered"
- end
- end
- local function finalResp(field, addr, message, param)
- log("[" .. addr .. "][" .. field:upper() .. "][INFO] " .. message)
- local mess = ser.serialize({RespType = field:upper(), Parameters = param})
- modem.send(addr, DNS_PORT, mess)
- end
- local function finalErr(field, addr, code, message)
- log("[" .. addr .. "][" .. field:upper() .. "][ERROR][" .. tostring(code) .. "] " .. message)
- local mess = ser.serialize({RespType = "DNSERROR", Parameters = {Error = {Code = code, Message = message}}})
- modem.send(addr, DNS_PORT, mess)
- end
- local function DNSResp(remoteAddr, domain)
- local addr = DNS(domain)
- if addr then
- finalResp("DNS", remoteAddr, "Domain " .. domain .. " --> " .. addr, {Address = addr})
- else
- finalErr("DNS", remoteAddr, 11, "No such domain")
- end
- end
- local function DNSSec(remoteAddr, key, publicKey, privateKey)
- local userKey = data.deserializeKey(key, "ec-public")
- if userKey then
- secureConnections[remoteAddr] = data.md5(data.sha256(data.ecdh(privateKey, userKey)))
- finalResp("SECDNS", remoteAddr, "Encryption key was succesfully created !", {Key = publicKey.serialize()})
- else
- finalErr("SECDNS", remoteAddr, 20, "Public key could not be read")
- end
- end
- local function AddDNS(remoteAddr, encrPass, domain, domAddress, owner)
- val, code, err = checkPassword(remoteAddr, encrPass)
- if val then
- if createDomain(domain, domAddress, owner) then
- finalResp("ADDDNS", remoteAddr, "Domain " .. domain .. " was successfully created", {Message = "Success"})
- else
- finalErr("ADDDNS", remoteAddr, 12, "Domain already exists")
- end
- else
- finalErr("ADDDNS", remoteAddr, code, err)
- end
- end
- local function DelDNS(remoteAddr, encrPass, domain)
- val, code, err = checkPassword(remoteAddr, encrPass)
- if val then
- if deleteDomain(domain) then
- finalResp("DELDNS", remoteAddr, "Domain " .. domain .. " was successfully deleted", {Message = "Success"})
- else
- finalErr("DELDNS", remoteAddr, 11, "No such domain")
- end
- else
- finalErr("DELDNS", remoteAddr, code, err)
- end
- end
- local function OwnDNS(remoteAddr, encrPass, domain)
- val, code, err = checkPassword(remoteAddr, encrPass)
- if val then
- local key = secureConnections[remoteAddr]
- _, owner = DNS(domain)
- if owner then
- local iv = data.random(16)
- finalResp("OWNDNS", remoteAddr, domain .. " owner was succesfully sent", {Owner = { Owner = data.encrypt(owner, key, iv), IV = iv}})
- else
- finalErr("OWNDNS", remoteAddr, 11, "No such domain")
- end
- else
- finalErr("OWNDNS", remoteAddr, code, err)
- end
- end
- local function network()
- modem.open(DNS_PORT)
- publicKey, privateKey = data.generateKeyPair()
- log(" --BDNS v" .. VERSION .. "--")
- while true do
- local event, localAddr, remoteAddr, port, dist, message = event.pull("modem_message")
- local request = ser.unserialize(message)
- if port == DNS_PORT and type(request) == "table" and type(request.ReqType) == "string" and type(request.Parameters) == "table" then
- if request.ReqType:upper() == "DNS" and type(request.Parameters.Domain) == "string" then
- -- {ReqType = "DNS", Parameters = {Domain = "domain.dom"}}
- DNSResp(remoteAddr, request.Parameters.Domain)
- elseif request.ReqType:upper() == "SECDNS" and type(request.Parameters.Key) == "string" then
- -- {ReqType = "SECDNS", Parameters = {Key = "public key"}}
- DNSSec(remoteAddr, request.Parameters.Key, publicKey, privateKey)
- elseif request.ReqType:upper() == "ADDDNS" and type(request.Parameters.Password) == "table" and type(request.Parameters.Domain) == "string" and type(request.Parameters.Address) == "string" and type(request.Parameters.Owner) == "string" then
- -- { ReqType = "ADDDNS", Parameters = { Domain = "domain.dom", Address = "a6cc03...", Owner = "lolo", Password = { Password = "encrypted password", IV = "random 16 bytes IV" } } }
- AddDNS(remoteAddr, request.Parameters.Password, request.Parameters.Domain, request.Parameters.Address, request.Parameters.Owner)
- elseif request.ReqType:upper() == "DELDNS" and type(request.Parameters.Password) == "table" and type(request.Parameters.Domain) == "string" then
- -- { ReqType = "DELDNS", Parameters = { Domain = "domain.dom", Password = { Password = "encrypted password", IV = "random 16 bytes IV" } } }
- DelDNS(remoteAddr, request.Parameters.Password, request.Parameters.Domain)
- elseif request.ReqType:upper() == "OWNDNS" and type(request.Parameters.Password) == "table" and type(request.Parameters.Domain) == "string" then
- -- { ReqType = "OWNDNS", Parameters = { Domain = "domain.dom", Password = { Password = "encrypted password", IV = "random 16 bytes IV" } } }
- OwnDNS(remoteAddr, request.Parameters.Password, request.Parameters.Domain)
- else
- finalErr("DNS", remoteAddr, 10, "Malformed request")
- end
- end
- end
- end
- term.clear()
- if not filesystem.isDirectory("/home/domains") then
- filesystem.makeDirectory("/home/domains")
- end
- if not exists("/home/password.pass") then
- local pass = nil
- local verif = nil
- while (not pass or not verif or pass ~= verif) do
- print("A password must be set to start the DNS Server")
- term.write("Password: ")
- pass = term.read({pwchar="*"})
- pass = strip(pass)
- print()
- term.write("Verification: ")
- verif = term.read({pwchar="*"})
- verif = strip(verif)
- term.clear()
- end
- local f = io.open("/home/password.pass", "w")
- f:write(data.sha256(pass))
- f:close()
- print("The DNS password is now set.")
- print("The server will start in 5 seconds.")
- os.sleep(5)
- term.clear()
- end
- network()
Advertisement
Add Comment
Please, Sign In to add comment