├── go.mod ├── .gitignore ├── Makefile ├── README.md ├── LICENSE └── logdns.go /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/kost/logdns 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/miekg/dns v1.1.43 7 | ) 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | dist/ 9 | # Test binary, built with `go test -c` 10 | *.test 11 | 12 | # Output of the go coverage tool, specifically when used with LiteIDE 13 | *.out 14 | 15 | # Dependency directories (remove the comment below to include it) 16 | # vendor/ 17 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | VERSION=1.0.1 2 | 3 | bin: 4 | go build 5 | 6 | dep: 7 | #go get -u ./... 8 | go get 9 | 10 | tools: 11 | go get github.com/mitchellh/gox 12 | get github.com/tcnksm/ghr 13 | 14 | ver: 15 | echo version $(VERSION) 16 | 17 | gittag: 18 | git tag v$(VERSION) 19 | git push --tags origin main 20 | 21 | clean: 22 | rm -rf dist 23 | 24 | dist: 25 | mkdir -p dist 26 | 27 | gox: 28 | CGO_ENABLED=0 gox -ldflags="-s -w" -osarch '!darwin/386' -output="dist/{{.Dir}}_{{.OS}}_{{.Arch}}" 29 | 30 | draft: 31 | ghr -draft v$(VERSION) dist/ 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # logdns 2 | Simple DNS logging server 3 | 4 | # Example 5 | 6 | Simple 7 | ``` 8 | ./logdns 9 | ``` 10 | 11 | # Usage 12 | 13 | ``` 14 | Usage of ./logdns 15 | -listen string 16 | listen address (default "0.0.0.0") 17 | -logfile string 18 | Log File name 19 | -port int 20 | port to listen (default 53) 21 | -resolve string 22 | which domains to respond, e.g. service. (default ".") 23 | -return string 24 | what address to return (default "127.0.0.1") 25 | -ttl string 26 | Set a custom ttl for returned records (default "3600") 27 | -verbose 28 | be verbose 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 kost 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /logdns.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "log" 7 | "os" 8 | "strconv" 9 | 10 | "github.com/miekg/dns" 11 | ) 12 | 13 | var ip string 14 | var VerboseLevel bool 15 | var Port int 16 | var myttl string 17 | var logfilename string 18 | 19 | func parseQuery(m *dns.Msg) { 20 | for _, q := range m.Question { 21 | if VerboseLevel { 22 | log.Printf("Query for %s: %v\n", q.Name, q.Qtype) 23 | } 24 | switch q.Qtype { 25 | case dns.TypeA: 26 | log.Printf("Query for %s\n", q.Name) 27 | rr, err := dns.NewRR(fmt.Sprintf("%s %s A %s", q.Name, myttl, ip)) 28 | if err == nil { 29 | m.Answer = append(m.Answer, rr) 30 | if VerboseLevel { 31 | log.Printf("Query for %s failed: %v\n", q.Name, err) 32 | } 33 | } 34 | } 35 | } 36 | } 37 | 38 | func handleDnsRequest(w dns.ResponseWriter, r *dns.Msg) { 39 | m := new(dns.Msg) 40 | m.SetReply(r) 41 | m.Compress = false 42 | 43 | if VerboseLevel { 44 | log.Printf("Query for \n") 45 | } 46 | switch r.Opcode { 47 | case dns.OpcodeQuery: 48 | parseQuery(m) 49 | } 50 | 51 | w.WriteMsg(m) 52 | } 53 | 54 | func main() { 55 | returnip := flag.String("return", "127.0.0.1", "what address to return") 56 | ttl := flag.String("ttl", "3600", "Set a custom ttl for returned records") 57 | listen := flag.String("listen", "0.0.0.0", "listen address") 58 | resolve := flag.String("resolve", ".", "which domains to respond, e.g. service.") 59 | verbose := flag.Bool("verbose", false, "be verbose") 60 | flag.IntVar(&Port, "port", 53, "port to listen") 61 | flag.StringVar(&logfilename, "logfile", "", "Log File name") 62 | 63 | flag.Parse() 64 | 65 | VerboseLevel = *verbose 66 | ip = *returnip 67 | myttl = *ttl 68 | 69 | dns.HandleFunc(*resolve, handleDnsRequest) 70 | 71 | // start server 72 | listenstr := *listen + ":" + strconv.Itoa(Port) 73 | server := &dns.Server{Addr: listenstr, Net: "udp"} 74 | log.Printf("Starting at %s\n", listenstr) 75 | 76 | if len(logfilename) > 0 { 77 | file, err := os.OpenFile(logfilename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666) 78 | if err != nil { 79 | log.Fatal(err) 80 | } 81 | log.SetOutput(file) 82 | } 83 | err := server.ListenAndServe() 84 | defer server.Shutdown() 85 | if err != nil { 86 | log.Fatalf("Failed to start server (check if you have permission to listen on specific port): %s\n ", err.Error()) 87 | } 88 | } 89 | --------------------------------------------------------------------------------