Compare commits

..

13 Commits

Author SHA1 Message Date
Star Brilliant 5723558934 Fix Accept header detection 2018-03-21 15:28:47 +08:00
Star Brilliant 2176e14e65 Extract date from Date header 2018-03-21 15:17:36 +08:00
Star Brilliant 1be3052cda Fix cache privateness 2018-03-21 15:08:12 +08:00
Star Brilliant 2b3a261247 Fix case issue 2018-03-21 04:14:45 +08:00
Star Brilliant 5f96e35f29 Add uninstallation instructions, fix #5 2018-03-21 03:48:57 +08:00
Star Brilliant 8034d5417d Update Readme 2018-03-21 03:21:06 +08:00
Star Brilliant b3f495e50f Use round for TTL values 2018-03-21 02:58:06 +08:00
Star Brilliant cefa3a6ba8 Fix HTTP header time zone 2018-03-21 02:52:22 +08:00
Star Brilliant a81a7eff58 It's time to flip the version number 2018-03-21 02:38:13 +08:00
Star Brilliant 26d4cd413d Revert "Skip go get if compiled"
This reverts commit 78e40722e8.
2018-03-21 02:27:55 +08:00
Star Brilliant fba928e4e4 Fix Makefile 2018-03-21 02:25:09 +08:00
Star Brilliant 78e40722e8 Skip go get if compiled 2018-03-21 02:18:05 +08:00
Star Brilliant ebaaa7ff71 Enable verbose for IETF protocol 2018-03-21 02:14:11 +08:00
7 changed files with 62 additions and 28 deletions
+2 -2
View File
@@ -25,8 +25,8 @@ uninstall:
deps: deps:
$(GOGET) ./doh-client ./doh-server $(GOGET) ./doh-client ./doh-server
doh-client/doh-client: deps doh-client/client.go doh-client/config.go doh-client/main.go json-dns/error.go json-dns/globalip.go json-dns/marshal.go json-dns/response.go json-dns/unmarshal.go doh-client/doh-client: deps doh-client/client.go doh-client/config.go doh-client/google.go doh-client/ietf.go doh-client/main.go json-dns/error.go json-dns/globalip.go json-dns/marshal.go json-dns/response.go json-dns/unmarshal.go
cd doh-client && $(GOBUILD) cd doh-client && $(GOBUILD)
doh-server/doh-server: deps doh-server/config.go doh-server/main.go doh-server/server.go json-dns/error.go json-dns/globalip.go json-dns/marshal.go json-dns/response.go json-dns/unmarshal.go doh-server/doh-server: deps doh-server/config.go doh-server/google.go doh-server/ietf.go doh-server/main.go doh-server/server.go json-dns/error.go json-dns/globalip.go json-dns/marshal.go json-dns/response.go json-dns/unmarshal.go
cd doh-server && $(GOBUILD) cd doh-server && $(GOBUILD)
+11 -4
View File
@@ -42,6 +42,14 @@ If it is OK, you will wee:
;; SERVER: 127.0.0.1#53(127.0.0.1) ;; SERVER: 127.0.0.1#53(127.0.0.1)
### Uninstalling
To uninstall, type:
sudo make uninstall
The configuration files are kept at `/etc/dns-over-https`. Remove them manually if you want.
## Server Configuration ## Server Configuration
The following is a typical DNS-over-HTTPS architecture: The following is a typical DNS-over-HTTPS architecture:
@@ -72,17 +80,16 @@ Client Subnet during your configuring `unbound` or `bind`.
## Protocol compatibility ## Protocol compatibility
### Google DNS-over-HTTPS ### Google DNS-over-HTTPS Protocol
DNS-over-HTTPS uses a protocol compatible to [Google DNS-over-HTTPS](https://developers.google.com/speed/public-dns/docs/dns-over-https), DNS-over-HTTPS uses a protocol compatible to [Google DNS-over-HTTPS](https://developers.google.com/speed/public-dns/docs/dns-over-https),
except for absolute expire time is preferred to relative TTL value. Refer to except for absolute expire time is preferred to relative TTL value. Refer to
[json-dns/response.go](json-dns/response.go) for a complete description of the [json-dns/response.go](json-dns/response.go) for a complete description of the
API. API.
### IETF DNS-over-HTTPS (Draft) ### IETF DNS-over-HTTPS Protocol (Draft)
DNS-over-HTTPS uses a protocol compatible to [draft-ietf-doh-dns-over-https DNS-over-HTTPS uses a protocol compatible to [draft-ietf-doh-dns-over-https](https://github.com/dohwg/draft-ietf-doh-dns-over-https).
](https://github.com/dohwg/draft-ietf-doh-dns-over-https).
This protocol is in draft stage. Any incompatibility may be introduced before This protocol is in draft stage. Any incompatibility may be introduced before
it is finished. it is finished.
+2 -2
View File
@@ -48,7 +48,7 @@ func (c *Client) handlerFuncGoogle(w dns.ResponseWriter, r *dns.Msg, isTCP bool)
w.WriteMsg(reply) w.WriteMsg(reply)
return return
} }
question := r.Question[0] question := &r.Question[0]
// knot-resolver scrambles capitalization, I think it is unfriendly to cache // knot-resolver scrambles capitalization, I think it is unfriendly to cache
questionName := strings.ToLower(question.Name) questionName := strings.ToLower(question.Name)
questionType := "" questionType := ""
@@ -88,7 +88,7 @@ func (c *Client) handlerFuncGoogle(w dns.ResponseWriter, r *dns.Msg, isTCP bool)
return return
} }
req.Header.Set("Accept", "application/json") req.Header.Set("Accept", "application/json")
req.Header.Set("User-Agent", "DNS-over-HTTPS/1.0 (+https://github.com/m13253/dns-over-https)") req.Header.Set("User-Agent", "DNS-over-HTTPS/1.1 (+https://github.com/m13253/dns-over-https)")
resp, err := c.httpClient.Do(req) resp, err := c.httpClient.Do(req)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
+20 -12
View File
@@ -49,7 +49,7 @@ func (c *Client) handlerFuncIETF(w dns.ResponseWriter, r *dns.Msg, isTCP bool) {
return return
} }
question := r.Question[0] question := &r.Question[0]
// knot-resolver scrambles capitalization, I think it is unfriendly to cache // knot-resolver scrambles capitalization, I think it is unfriendly to cache
questionName := strings.ToLower(question.Name) questionName := strings.ToLower(question.Name)
questionType := "" questionType := ""
@@ -140,7 +140,7 @@ func (c *Client) handlerFuncIETF(w dns.ResponseWriter, r *dns.Msg, isTCP bool) {
req.Header.Set("Content-Type", "application/dns-udpwireformat") req.Header.Set("Content-Type", "application/dns-udpwireformat")
} }
req.Header.Set("Accept", "application/dns-udpwireformat") req.Header.Set("Accept", "application/dns-udpwireformat")
req.Header.Set("User-Agent", "DNS-over-HTTPS/1.0 (+https://github.com/m13253/dns-over-https)") req.Header.Set("User-Agent", "DNS-over-HTTPS/1.1 (+https://github.com/m13253/dns-over-https)")
resp, err := c.httpClient.Do(req) resp, err := c.httpClient.Do(req)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
@@ -166,17 +166,25 @@ func (c *Client) handlerFuncIETF(w dns.ResponseWriter, r *dns.Msg, isTCP bool) {
w.WriteMsg(reply) w.WriteMsg(reply)
return return
} }
lastModified := resp.Header.Get("Last-Modified") headerNow := resp.Header.Get("Date")
if lastModified == "" { now := time.Now().UTC()
lastModified = resp.Header.Get("Date") if headerNow != "" {
} if nowDate, err := time.Parse(http.TimeFormat, headerNow); err == nil {
now := time.Now() now = nowDate
lastModifiedDate, err := time.Parse(http.TimeFormat, lastModified) } else {
if err != nil {
log.Println(err) log.Println(err)
lastModifiedDate = now
} }
timeDelta := now.Sub(lastModifiedDate) }
headerLastModified := resp.Header.Get("Last-Modified")
lastModified := now
if headerLastModified != "" {
if lastModifiedDate, err := time.Parse(http.TimeFormat, headerLastModified); err == nil {
lastModified = lastModifiedDate
} else {
log.Println(err)
}
}
timeDelta := now.Sub(lastModified)
if timeDelta < 0 { if timeDelta < 0 {
timeDelta = 0 timeDelta = 0
} }
@@ -227,7 +235,7 @@ func fixRecordTTL(rr dns.RR, delta time.Duration) dns.RR {
rrHeader := rr.Header() rrHeader := rr.Header()
oldTTL := time.Duration(rrHeader.Ttl) * time.Second oldTTL := time.Duration(rrHeader.Ttl) * time.Second
newTTL := oldTTL - delta newTTL := oldTTL - delta
if newTTL >= 0 { if newTTL > 0 {
rrHeader.Ttl = uint32(newTTL / time.Second) rrHeader.Ttl = uint32(newTTL / time.Second)
} else { } else {
rrHeader.Ttl = 0 rrHeader.Ttl = 0
+2 -2
View File
@@ -180,9 +180,9 @@ func (s *Server) generateResponseGoogle(w http.ResponseWriter, r *http.Request,
w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.Header().Set("Content-Type", "application/json; charset=UTF-8")
if respJSON.HaveTTL { if respJSON.HaveTTL {
if req.isTailored { if req.isTailored {
w.Header().Set("Cache-Control", "public, max-age="+strconv.Itoa(int(respJSON.LeastTTL)))
} else {
w.Header().Set("Cache-Control", "private, max-age="+strconv.Itoa(int(respJSON.LeastTTL))) w.Header().Set("Cache-Control", "private, max-age="+strconv.Itoa(int(respJSON.LeastTTL)))
} else {
w.Header().Set("Cache-Control", "public, max-age="+strconv.Itoa(int(respJSON.LeastTTL)))
} }
w.Header().Set("Expires", respJSON.EarliestExpires.Format(http.TimeFormat)) w.Header().Set("Expires", respJSON.EarliestExpires.Format(http.TimeFormat))
} }
+22 -3
View File
@@ -68,6 +68,25 @@ func (s *Server) parseRequestIETF(w http.ResponseWriter, r *http.Request) *DNSRe
errtext: fmt.Sprintf("DNS packet parse failure (%s)", err.Error()), errtext: fmt.Sprintf("DNS packet parse failure (%s)", err.Error()),
} }
} }
if s.conf.Verbose && len(msg.Question) > 0 {
question := &msg.Question[0]
questionName := question.Name
questionClass := ""
if qclass, ok := dns.ClassToString[question.Qclass]; ok {
questionClass = qclass
} else {
questionClass = strconv.Itoa(int(question.Qclass))
}
questionType := ""
if qtype, ok := dns.TypeToString[question.Qtype]; ok {
questionType = qtype
} else {
questionType = strconv.Itoa(int(question.Qtype))
}
fmt.Printf("%s - - [%s] \"%s %s %s\"\n", r.RemoteAddr, time.Now().Format("02/Jan/2006:15:04:05 -0700"), questionName, questionClass, questionType)
}
msg.Id = dns.Id() msg.Id = dns.Id()
opt := msg.IsEdns0() opt := msg.IsEdns0()
if opt == nil { if opt == nil {
@@ -126,14 +145,14 @@ func (s *Server) generateResponseIETF(w http.ResponseWriter, r *http.Request, re
} }
w.Header().Set("Content-Type", "application/dns-udpwireformat") w.Header().Set("Content-Type", "application/dns-udpwireformat")
now := time.Now().Format(http.TimeFormat) now := time.Now().UTC().Format(http.TimeFormat)
w.Header().Set("Date", now) w.Header().Set("Date", now)
w.Header().Set("Last-Modified", now) w.Header().Set("Last-Modified", now)
if respJSON.HaveTTL { if respJSON.HaveTTL {
if req.isTailored { if req.isTailored {
w.Header().Set("Cache-Control", "public, max-age="+strconv.Itoa(int(respJSON.LeastTTL)))
} else {
w.Header().Set("Cache-Control", "private, max-age="+strconv.Itoa(int(respJSON.LeastTTL))) w.Header().Set("Cache-Control", "private, max-age="+strconv.Itoa(int(respJSON.LeastTTL)))
} else {
w.Header().Set("Cache-Control", "public, max-age="+strconv.Itoa(int(respJSON.LeastTTL)))
} }
w.Header().Set("Expires", respJSON.EarliestExpires.Format(http.TimeFormat)) w.Header().Set("Expires", respJSON.EarliestExpires.Format(http.TimeFormat))
} }
+3 -3
View File
@@ -82,8 +82,8 @@ func (s *Server) Start() error {
} }
func (s *Server) handlerFunc(w http.ResponseWriter, r *http.Request) { func (s *Server) handlerFunc(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Server", "DNS-over-HTTPS/1.0 (+https://github.com/m13253/dns-over-https)") w.Header().Set("Server", "DNS-over-HTTPS/1.1 (+https://github.com/m13253/dns-over-https)")
w.Header().Set("X-Powered-By", "DNS-over-HTTPS/1.0 (+https://github.com/m13253/dns-over-https)") w.Header().Set("X-Powered-By", "DNS-over-HTTPS/1.1 (+https://github.com/m13253/dns-over-https)")
if r.Form == nil { if r.Form == nil {
const maxMemory = 32 << 20 // 32 MB const maxMemory = 32 << 20 // 32 MB
@@ -142,7 +142,7 @@ func (s *Server) handlerFunc(w http.ResponseWriter, r *http.Request) {
return return
} }
if contentType == "application/x-www-form-urlencoded" { if responseType == "application/json" {
s.generateResponseGoogle(w, r, req) s.generateResponseGoogle(w, r, req)
} else if contentType == "application/dns-udpwireformat" { } else if contentType == "application/dns-udpwireformat" {
s.generateResponseIETF(w, r, req) s.generateResponseIETF(w, r, req)