From 8f017d2c0e25969bd86eafa4adbc184e41c61dc0 Mon Sep 17 00:00:00 2001
From: Simon Zolin <s.zolin@adguard.com>
Date: Tue, 18 Aug 2020 14:26:01 +0300
Subject: [PATCH 1/6] * DNS: use REFUSED DNS error code as the default blocking
 method

---
 dnsforward/dnsforward_test.go | 10 ++++------
 dnsforward/handle_dns.go      |  2 +-
 dnsforward/msg.go             | 14 +++++++++++---
 3 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/dnsforward/dnsforward_test.go b/dnsforward/dnsforward_test.go
index a3eb94f1..825a6e88 100644
--- a/dnsforward/dnsforward_test.go
+++ b/dnsforward/dnsforward_test.go
@@ -227,7 +227,7 @@ func TestBlockedRequest(t *testing.T) {
 	addr := s.dnsProxy.Addr(proxy.ProtoUDP)
 
 	//
-	// NXDomain blocking
+	// Default blocking - REFUSED
 	//
 	req := dns.Msg{}
 	req.Id = dns.Id()
@@ -240,9 +240,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 {
@@ -404,7 +402,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:
@@ -419,7 +417,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..0df35bfc 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 {
@@ -68,11 +68,11 @@ func (s *Server) genDNSFilterMessage(d *proxy.DNSContext, result *dnsfilter.Resu
 
 		// 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 +182,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)

From f0ebec545e2c96060a13fb6bb30f17bc6326ef8c Mon Sep 17 00:00:00 2001
From: Simon Zolin <s.zolin@adguard.com>
Date: Tue, 18 Aug 2020 18:14:09 +0300
Subject: [PATCH 2/6] * locales: blocking_mode_default: NXDOMAIN -> REFUSED

---
 client/src/__locales/en.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json
index e8e984e2..d6c2cd5c 100644
--- a/client/src/__locales/en.json
+++ b/client/src/__locales/en.json
@@ -249,7 +249,7 @@
     "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_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",

From b6193c32ceb814ad305017854ad4bb2115f7cfbf Mon Sep 17 00:00:00 2001
From: Simon Zolin <s.zolin@adguard.com>
Date: Wed, 19 Aug 2020 14:13:16 +0300
Subject: [PATCH 3/6] + DNS: new blocking mode: "refused"

---
 AGHTechDoc.md                 | 4 ++--
 dnsforward/dnsforward_http.go | 2 +-
 dnsforward/msg.go             | 5 +++++
 openapi/openapi.yaml          | 1 +
 4 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/AGHTechDoc.md b/AGHTechDoc.md
index e5e582ec..49b62d52 100644
--- a/AGHTechDoc.md
+++ b/AGHTechDoc.md
@@ -990,7 +990,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,
@@ -1015,7 +1015,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/dnsforward/dnsforward_http.go b/dnsforward/dnsforward_http.go
index 63e82d95..f3dc35e0 100644
--- a/dnsforward/dnsforward_http.go
+++ b/dnsforward/dnsforward_http.go
@@ -74,7 +74,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/msg.go b/dnsforward/msg.go
index 0df35bfc..fc4ecb51 100644
--- a/dnsforward/msg.go
+++ b/dnsforward/msg.go
@@ -64,6 +64,11 @@ 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
diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml
index 57d63c70..7fd48870 100644
--- a/openapi/openapi.yaml
+++ b/openapi/openapi.yaml
@@ -1007,6 +1007,7 @@ components:
                     type: string
                     enum:
                         - default
+                        - refused
                         - nxdomain
                         - null_ip
                         - custom_ip

From 12ed67ab1154138c0008f18b6fb7ac8a17f43860 Mon Sep 17 00:00:00 2001
From: ArtemBaskal <a.baskal@adguard.com>
Date: Mon, 7 Sep 2020 12:38:35 +0300
Subject: [PATCH 4/6] + client: Add REFUSED DNS error code as the default
 blocking method

---
 client/src/__locales/en.json    | 1 +
 client/src/helpers/constants.js | 1 +
 2 files changed, 2 insertions(+)

diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json
index d6c2cd5c..fe21ef6c 100644
--- a/client/src/__locales/en.json
+++ b/client/src/__locales/en.json
@@ -235,6 +235,7 @@
     "blocking_mode": "Blocking mode",
     "default": "Default",
     "nxdomain": "NXDOMAIN",
+    "refused": "REFUSED",
     "null_ip": "Null IP",
     "custom_ip": "Custom IP",
     "blocking_ipv4": "Blocking IPv4",
diff --git a/client/src/helpers/constants.js b/client/src/helpers/constants.js
index e0075a25..163b11a6 100644
--- a/client/src/helpers/constants.js
+++ b/client/src/helpers/constants.js
@@ -294,6 +294,7 @@ export const FILTERS_INTERVALS_HOURS = [0, 1, 12, 24, 72, 168];
 
 export const BLOCKING_MODES = {
     default: 'default',
+    refused: 'refused',
     nxdomain: 'nxdomain',
     null_ip: 'null_ip',
     custom_ip: 'custom_ip',

From 317e030554ecaaa9c32e187c4aecca9e87283e40 Mon Sep 17 00:00:00 2001
From: Andrey Meshkov <am@adguard.com>
Date: Wed, 9 Sep 2020 13:59:18 +0300
Subject: [PATCH 5/6] * (ui): added refused string

---
 client/src/__locales/en.json | 1 +
 1 file changed, 1 insertion(+)

diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json
index 791bb301..c1aaa839 100644
--- a/client/src/__locales/en.json
+++ b/client/src/__locales/en.json
@@ -256,6 +256,7 @@
     "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 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",

From 382cddea47452abd02adeab2a1539dcd3c74c1dd Mon Sep 17 00:00:00 2001
From: Andrey Meshkov <am@adguard.com>
Date: Wed, 9 Sep 2020 14:03:27 +0300
Subject: [PATCH 6/6] fix pre-commit hook

---
 .githooks/pre-commit            | 4 +++-
 client/src/helpers/constants.js | 2 ++
 2 files changed, 5 insertions(+), 1 deletion(-)

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/client/src/helpers/constants.js b/client/src/helpers/constants.js
index 69450297..cae6f597 100644
--- a/client/src/helpers/constants.js
+++ b/client/src/helpers/constants.js
@@ -293,6 +293,8 @@ 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',