diff --git a/.githooks/pre-commit b/.githooks/pre-commit index 4fd4e4f5..9889db34 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -1,8 +1,10 @@ #!/bin/bash set -e; + +found=0 git diff --cached --name-only | grep -q '.js$' && found=1 if [ $found == 1 ]; then - make lint-js || exit 1 + npm --prefix client run lint || exit 1 npm run test --prefix client || exit 1 fi diff --git a/AGHTechDoc.md b/AGHTechDoc.md index 1a90fd91..0041f3e2 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -993,7 +993,7 @@ Response: "protection_enabled": true | false, "ratelimit": 1234, - "blocking_mode": "default" | "nxdomain" | "null_ip" | "custom_ip", + "blocking_mode": "default" | "refused" | "nxdomain" | "null_ip" | "custom_ip", "blocking_ipv4": "1.2.3.4", "blocking_ipv6": "1:2:3::4", "edns_cs_enabled": true | false, @@ -1019,7 +1019,7 @@ Request: "protection_enabled": true | false, "ratelimit": 1234, - "blocking_mode": "default" | "nxdomain" | "null_ip" | "custom_ip", + "blocking_mode": "default" | "refused" | "nxdomain" | "null_ip" | "custom_ip", "blocking_ipv4": "1.2.3.4", "blocking_ipv6": "1:2:3::4", "edns_cs_enabled": true | false, diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index 001b7a09..ece13f64 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -241,6 +241,7 @@ "blocking_mode": "Blocking mode", "default": "Default", "nxdomain": "NXDOMAIN", + "refused": "REFUSED", "null_ip": "Null IP", "custom_ip": "Custom IP", "blocking_ipv4": "Blocking IPv4", @@ -255,7 +256,8 @@ "rate_limit_desc": "The number of requests per second that a single client is allowed to make (0: unlimited)", "blocking_ipv4_desc": "IP address to be returned for a blocked A request", "blocking_ipv6_desc": "IP address to be returned for a blocked AAAA request", - "blocking_mode_default": "Default: Respond with NXDOMAIN when blocked by Adblock-style rule; respond with the IP address specified in the rule when blocked by /etc/hosts-style rule", + "blocking_mode_default": "Default: Respond with REFUSED when blocked by Adblock-style rule; respond with the IP address specified in the rule when blocked by /etc/hosts-style rule", + "blocking_mode_refused": "REFUSED: Respond with REFUSED code", "blocking_mode_nxdomain": "NXDOMAIN: Respond with NXDOMAIN code", "blocking_mode_null_ip": "Null IP: Respond with zero IP address (0.0.0.0 for A; :: for AAAA)", "blocking_mode_custom_ip": "Custom IP: Respond with a manually set IP address", diff --git a/client/src/helpers/constants.js b/client/src/helpers/constants.js index 80b2ddf9..86ed844d 100644 --- a/client/src/helpers/constants.js +++ b/client/src/helpers/constants.js @@ -294,8 +294,11 @@ export const QUERY_LOG_INTERVALS_DAYS = [1, 7, 30, 90]; export const FILTERS_INTERVALS_HOURS = [0, 1, 12, 24, 72, 168]; +// Note that translation strings contain these modes (blocking_mode_CONSTANT) +// i.e. blocking_mode_default, blocking_mode_null_ip export const BLOCKING_MODES = { default: 'default', + refused: 'refused', nxdomain: 'nxdomain', null_ip: 'null_ip', custom_ip: 'custom_ip', diff --git a/dnsforward/dnsforward_http.go b/dnsforward/dnsforward_http.go index 1d5fe153..42c738f2 100644 --- a/dnsforward/dnsforward_http.go +++ b/dnsforward/dnsforward_http.go @@ -76,7 +76,7 @@ func (s *Server) handleGetConfig(w http.ResponseWriter, r *http.Request) { func checkBlockingMode(req dnsConfigJSON) bool { bm := req.BlockingMode - if !(bm == "default" || bm == "nxdomain" || bm == "null_ip" || bm == "custom_ip") { + if !(bm == "default" || bm == "refused" || bm == "nxdomain" || bm == "null_ip" || bm == "custom_ip") { return false } diff --git a/dnsforward/dnsforward_test.go b/dnsforward/dnsforward_test.go index a183d786..664a5c1b 100644 --- a/dnsforward/dnsforward_test.go +++ b/dnsforward/dnsforward_test.go @@ -263,7 +263,7 @@ func TestBlockedRequest(t *testing.T) { addr := s.dnsProxy.Addr(proxy.ProtoUDP) // - // NXDomain blocking + // Default blocking - REFUSED // req := dns.Msg{} req.Id = dns.Id() @@ -276,9 +276,7 @@ func TestBlockedRequest(t *testing.T) { if err != nil { t.Fatalf("Couldn't talk to server %s: %s", addr, err) } - if reply.Rcode != dns.RcodeNameError { - t.Fatalf("Wrong response: %s", reply.String()) - } + assert.Equal(t, dns.RcodeRefused, reply.Rcode) err = s.Stop() if err != nil { @@ -440,7 +438,7 @@ func TestBlockCNAME(t *testing.T) { req := createTestMessage("badhost.") reply, err := dns.Exchange(req, addr.String()) assert.Nil(t, err, nil) - assert.Equal(t, dns.RcodeNameError, reply.Rcode) + assert.Equal(t, dns.RcodeRefused, reply.Rcode) // 'whitelist.example.org' has a canonical name 'null.example.org' which is blocked by filters // but 'whitelist.example.org' is in a whitelist: @@ -455,7 +453,7 @@ func TestBlockCNAME(t *testing.T) { req = createTestMessage("example.org.") reply, err = dns.Exchange(req, addr.String()) assert.Nil(t, err) - assert.Equal(t, dns.RcodeNameError, reply.Rcode) + assert.Equal(t, dns.RcodeRefused, reply.Rcode) _ = s.Stop() } diff --git a/dnsforward/handle_dns.go b/dnsforward/handle_dns.go index 3f0f7911..f864865b 100644 --- a/dnsforward/handle_dns.go +++ b/dnsforward/handle_dns.go @@ -88,7 +88,7 @@ func processInitial(ctx *dnsContext) int { // disable Mozilla DoH if (d.Req.Question[0].Qtype == dns.TypeA || d.Req.Question[0].Qtype == dns.TypeAAAA) && d.Req.Question[0].Name == "use-application-dns.net." { - d.Res = s.genNXDomain(d.Req) + d.Res = s.makeResponseREFUSED(d.Req) return resultFinish } diff --git a/dnsforward/msg.go b/dnsforward/msg.go index a1078539..fc4ecb51 100644 --- a/dnsforward/msg.go +++ b/dnsforward/msg.go @@ -24,7 +24,7 @@ func (s *Server) genDNSFilterMessage(d *proxy.DNSContext, result *dnsfilter.Resu m := d.Req if m.Question[0].Qtype != dns.TypeA && m.Question[0].Qtype != dns.TypeAAAA { - return s.genNXDomain(m) + return s.makeResponseREFUSED(m) } switch result.Reason { @@ -64,15 +64,20 @@ func (s *Server) genDNSFilterMessage(d *proxy.DNSContext, result *dnsfilter.Resu // means that we should return NXDOMAIN for any blocked request return s.genNXDomain(m) + + } else if s.conf.BlockingMode == "refused" { + // means that we should return NXDOMAIN for any blocked request + + return s.makeResponseREFUSED(m) } // Default blocking mode // If there's an IP specified in the rule, return it - // If there is no IP, return NXDOMAIN + // If there is no IP, return REFUSED if result.IP != nil { return s.genResponseWithIP(m, result.IP) } - return s.genNXDomain(m) + return s.makeResponseREFUSED(m) } } @@ -182,6 +187,14 @@ func (s *Server) genCNAMEAnswer(req *dns.Msg, cname string) *dns.CNAME { return answer } +// Create REFUSED DNS response +func (s *Server) makeResponseREFUSED(request *dns.Msg) *dns.Msg { + resp := dns.Msg{} + resp.SetRcode(request, dns.RcodeRefused) + resp.RecursionAvailable = true + return &resp +} + func (s *Server) genNXDomain(request *dns.Msg) *dns.Msg { resp := dns.Msg{} resp.SetRcode(request, dns.RcodeNameError) diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index b68a9ca6..d7a5d2cd 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -1009,6 +1009,7 @@ components: type: string enum: - default + - refused - nxdomain - null_ip - custom_ip