This repository has been archived by the owner on Mar 15, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
main.go
93 lines (76 loc) · 2.11 KB
/
main.go
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package main
import (
"database/sql"
"flag"
"fmt"
"log"
"net"
"os/user"
"path/filepath"
"strings"
_ "github.com/mattn/go-sqlite3"
"github.com/miekg/dns"
)
var nixopsStateDb *sql.DB
func openNixopsStateDb() *sql.DB {
usr, _ := user.Current()
db, err := sql.Open("sqlite3", filepath.Join(
usr.HomeDir, ".nixops/deployments.nixops")+"?mode=ro")
if err != nil {
log.Fatal(err)
}
return db
}
func nixopsHostIp(hostname string) (net.IP, error) {
var ip string
row := nixopsStateDb.QueryRow(`
select ra.value from Resources r, ResourceAttrs ra
where r.name = ? and r.id = ra.machine and ra.name = 'privateIpv4'
`, hostname)
if err := row.Scan(&ip); err != nil {
return nil, fmt.Errorf("Error while trying to find host '%s' in NixOps: %q",
hostname, err)
}
return net.ParseIP(ip), nil
}
func domainHandler(domain string) func(dns.ResponseWriter, *dns.Msg) {
return func(w dns.ResponseWriter, r *dns.Msg) {
q := r.Question[0]
log.Printf("Question: Type=%s Class=%s Name=%s\n", dns.TypeToString[q.Qtype], dns.ClassToString[q.Qclass], q.Name)
if q.Qtype != dns.TypeA || q.Qclass != dns.ClassINET {
handleNotFound(w, r)
return
}
ip, err := nixopsHostIp(strings.TrimSuffix(q.Name, fmt.Sprintf("%s.", domain)))
if err != nil {
log.Println(err)
handleNotFound(w, r)
return
}
m := new(dns.Msg)
m.SetReply(r)
a := new(dns.A)
a.Hdr = dns.RR_Header{Name: q.Name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 30}
a.A = ip
m.Answer = []dns.RR{a}
w.WriteMsg(m)
}
}
func handleNotFound(w dns.ResponseWriter, r *dns.Msg) {
m := new(dns.Msg)
m.SetReply(r)
m.Rcode = dns.RcodeNameError // NXDOMAIN
w.WriteMsg(m)
}
func main() {
var addr = flag.String("addr", "127.0.0.1:5300", "listen address")
var domain = flag.String("domain", "",
"fake domain name to strip from requests e.g. host.ops -> host if -domain=.ops")
flag.Parse()
nixopsStateDb = openNixopsStateDb()
defer nixopsStateDb.Close()
server := &dns.Server{Addr: *addr, Net: "udp"}
server.Handler = dns.HandlerFunc(domainHandler(*domain))
log.Printf("Listening on %s\n", *addr)
log.Fatal(server.ListenAndServe())
}