Hi!
I’d like to build a simple forwarding DNS server using ocaml-dns and its example code in forward.ml.
I’ve tried to add names as A records to the local database like this:
Loader.add_a_rr
(Ipaddr.V4.of_string_exn "192.168.1.1")
(Int32.of_int 86400)
(Name.of_string "foo")
db;
I use dig to query the forwarding DNS server:
dig @localhost -p 53530 foo A
The queried names are never found in the local database. Every request produces
ServFail: no local match for foo, forwarding...
What is the correct way to fill the trie database?
I’m using OCaml 4.06.1 with dns 1.0.1 (installed via OPAM) on Debian 9.
Thank you in advance!
This is my code:
(* Forwarding DNS server example. Looks up query locally first then forwards to another resolver. *)
open Lwt
open Dns
let rcode_to_string = function
| Packet.NoError -> "NoError"
| Packet.FormErr -> "FormErr"
| Packet.ServFail -> "ServFail (TrieCorrupt)"
| Packet.NXDomain -> "NXDomain"
| Packet.NotImp -> "NotImp"
| Packet.Refused -> "Refused"
| Packet.YXDomain -> "YXDomain"
| Packet.YXRRSet -> "YXRRSet"
| Packet.NXRRSet -> "NXRRSet"
| Packet.NotAuth -> "NotAuth"
| Packet.NotZone -> "NotZone"
| Packet.BadVers -> "BadVers"
| Packet.BadKey -> "BadKey"
| Packet.BadTime -> "BadTime"
| Packet.BadMode -> "BadMode"
| Packet.BadName -> "BadName"
| Packet.BadAlg -> "BadAlg"
(* check db first, then fall back to resolver on error *)
let process db resolver ~src ~dst packet =
let open Packet in
match packet.questions with
| [] -> return None; (* no questions in packet *)
| [q] -> begin
let answer = Query.(answer q.q_name q.q_type db.Loader.trie) in (* query local db *)
match answer.Query.rcode with
| Packet.NoError -> (* local match *)
Lwt_io.printf "Local match for %s\n" (Name.to_string q.q_name)
>>= fun() ->
return (Some answer)
| rc -> (* no match, forward *)
Lwt_io.printf "%s: no local match for %s, forwarding...\n" (rcode_to_string rc) (Name.to_string q.q_name)
>>= fun() ->
Dns_resolver_unix.resolve resolver q.q_class q.q_type q.q_name
>>= fun result ->
(return (Some (Dns.Query.answer_of_response result)))
end
| _::_::_ -> return None
let () =
Lwt_main.run (
let address = "127.0.0.1" in (* listen on localhost *)
let port = 53530 in
let db = Loader.new_db () in (* create new empty db *)
(* Etc_hosts.add db; *)
Loader.add_a_rr
(Ipaddr.V4.of_string_exn "192.168.1.1")
(Int32.of_int 86400)
(Name.of_string "foo")
db;
(* Loader.no_more_updates db; *)
Dns_resolver_unix.create () (* create resolver using /etc/resolv.conf *)
>>= fun resolver ->
let processor = ((Dns_server.processor_of_process (process db resolver)) :> (module Dns_server.PROCESSOR)) in
Dns_server_unix.serve_with_processor ~address ~port ~processor)