这个DNS系列现在有以下几篇文章
完整代码请看DNS
DOH就比较简单了,因为DOH使用的请求数据和应答数据均为之前的DNS协议格式,包括DNS,EDNS,DNSSEC…当然是否支持EDNS,DNSSEC需要看DNS服务器的支持情况
DOH的最主要的区别是把DNS使用的UDP,换成了HTTPS,这样就能防止DNS污染了,而且可以使用DNSSEC加上ESNI来防止证书劫持,DOH的协议在rfc8484中有定义
DOH主要有两种方式HTTP的GET请求和POST的请求
GET
GET请求需要使用BASE64对请求的字节数据进行序列化,然后作为参数传递,获取到的数据使用我们之前的解析进行解析就行了
func get(dReq []byte, server string) (body []byte, err error) { query := strings.Replace(base64.URLEncoding.EncodeToString(dReq), "=", "", -1) urls := "https://" + server + "/dns-query?dns=" + query res, err := http.Get(urls) if err != nil { return nil, err } defer res.Body.Close() body, err = ioutil.ReadAll(res.Body) if err != nil { return nil, err } return}
POST
POST并不需要进行序列化,直接把原始请求数据作为body就行了
func post(dReq []byte, server string) (body []byte, err error) { client := &http.Client{Timeout: 5 * time.Second} req, err := http.NewRequest(http.MethodPost, "", bytes.NewReader(dReq)) if err != nil { return nil, fmt.Errorf("DOH:post() newReq -> %v", err) } urls, err := url.Parse("//" + server) if err != nil { return nil, fmt.Errorf("DOH:post() urlParse -> %v", err) } req.URL.Scheme = "https" req.URL.Host = urls.Host req.URL.Path = urls.Path + "/dns-query" req.Header.Set("accept", "application/dns-message") req.Header.Set("content-type", "application/dns-message") req.ContentLength = int64(len(dReq)) resp, err := client.Do(req) if err != nil { return nil, fmt.Errorf("DOH:post() req -> %v", err) } defer resp.Body.Close() body, err = ioutil.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("DOH:post() readBody -> %v", err) } return}
完整代码请看开头
0 条评论