diff --git a/Apps/DropRequestsApp/App.cs b/Apps/DropRequestsApp/App.cs
new file mode 100644
index 00000000..e9b037b3
--- /dev/null
+++ b/Apps/DropRequestsApp/App.cs
@@ -0,0 +1,192 @@
+/*
+Technitium DNS Server
+Copyright (C) 2021 Shreyas Zare (shreyas@technitium.com)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+
+*/
+
+using DnsApplicationCommon;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Threading.Tasks;
+using TechnitiumLibrary.Net;
+using TechnitiumLibrary.Net.Dns;
+
+namespace DropRequests
+{
+ public class App : IDnsRequestController
+ {
+ #region variables
+
+ bool _enableBlocking;
+ IReadOnlyList _allowedNetworks;
+ IReadOnlyList _blockedNetworks;
+ IReadOnlyList _blockedQuestions;
+
+ #endregion
+
+ #region IDisposable
+
+ public void Dispose()
+ {
+ //do nothing
+ }
+
+ #endregion
+
+ #region public
+
+ public Task InitializeAsync(IDnsServer dnsServer, string config)
+ {
+ dynamic jsonConfig = JsonConvert.DeserializeObject(config);
+
+ _enableBlocking = jsonConfig.enableBlocking.Value;
+
+ if (jsonConfig.allowedNetworks is null)
+ {
+ _allowedNetworks = Array.Empty();
+ }
+ else
+ {
+ List allowedNetworks = new List();
+
+ foreach (dynamic allowedNetwork in jsonConfig.allowedNetworks)
+ {
+ allowedNetworks.Add(NetworkAddress.Parse(allowedNetwork.Value));
+ }
+
+ _allowedNetworks = allowedNetworks;
+ }
+
+ if (jsonConfig.blockedNetworks is null)
+ {
+ _blockedNetworks = Array.Empty();
+ }
+ else
+ {
+ List blockedNetworks = new List();
+
+ foreach (dynamic blockedNetwork in jsonConfig.blockedNetworks)
+ {
+ blockedNetworks.Add(NetworkAddress.Parse(blockedNetwork.Value));
+ }
+
+ _blockedNetworks = blockedNetworks;
+ }
+
+ if (jsonConfig.blockedQuestions is null)
+ {
+ _blockedQuestions = Array.Empty();
+ }
+ else
+ {
+ List blockedQuestions = new List();
+
+ foreach (dynamic blockedQuestion in jsonConfig.blockedQuestions)
+ {
+ blockedQuestions.Add(new BlockedQuestion(blockedQuestion));
+ }
+
+ _blockedQuestions = blockedQuestions;
+ }
+
+ return Task.CompletedTask;
+ }
+
+ public Task GetRequestActionAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol)
+ {
+ if (!_enableBlocking)
+ return Task.FromResult(DnsRequestControllerAction.Allow);
+
+ IPAddress remoteIp = remoteEP.Address;
+
+ foreach (NetworkAddress allowedNetwork in _allowedNetworks)
+ {
+ if (allowedNetwork.Contains(remoteIp))
+ return Task.FromResult(DnsRequestControllerAction.Allow);
+ }
+
+ foreach (NetworkAddress blockedNetwork in _blockedNetworks)
+ {
+ if (blockedNetwork.Contains(remoteIp))
+ return Task.FromResult(DnsRequestControllerAction.DropSilently);
+ }
+
+ if (request.Question.Count != 1)
+ return Task.FromResult(DnsRequestControllerAction.DropSilently);
+
+ DnsQuestionRecord requestQuestion = request.Question[0];
+
+ foreach (BlockedQuestion blockedQuestion in _blockedQuestions)
+ {
+ if (blockedQuestion.Matches(requestQuestion))
+ return Task.FromResult(DnsRequestControllerAction.DropSilently);
+ }
+
+ return Task.FromResult(DnsRequestControllerAction.Allow);
+ }
+
+ #endregion
+
+ #region properties
+
+ public string Description
+ { get { return "Drop incoming DNS requests that match the rules in the config."; } }
+
+ #endregion
+
+ class BlockedQuestion
+ {
+ #region variables
+
+ readonly string _name;
+ readonly DnsResourceRecordType _type;
+
+ #endregion
+
+ #region constructor
+
+ public BlockedQuestion(dynamic jsonQuestion)
+ {
+ _name = jsonQuestion.name?.Value;
+
+ string strType = jsonQuestion.type?.Value;
+ if (!string.IsNullOrEmpty(strType) && Enum.TryParse(strType, true, out DnsResourceRecordType type))
+ _type = type;
+ else
+ _type = DnsResourceRecordType.Unknown;
+ }
+
+ #endregion
+
+ #region public
+
+ public bool Matches(DnsQuestionRecord question)
+ {
+ if ((_name is not null) && !_name.Equals(question.Name, StringComparison.OrdinalIgnoreCase))
+ return false;
+
+ if ((_type != DnsResourceRecordType.Unknown) && (_type != question.Type))
+ return false;
+
+ return true;
+ }
+
+ #endregion
+ }
+ }
+}
diff --git a/Apps/DropRequestsApp/DropRequestsApp.csproj b/Apps/DropRequestsApp/DropRequestsApp.csproj
new file mode 100644
index 00000000..1f636813
--- /dev/null
+++ b/Apps/DropRequestsApp/DropRequestsApp.csproj
@@ -0,0 +1,41 @@
+
+
+
+ net5.0
+ false
+ 1.0
+ Technitium
+ Technitium DNS Server
+ Shreyas Zare
+ DropRequestsApp
+ DropRequests
+ https://technitium.com/dns/
+ https://github.com/TechnitiumSoftware/DnsServer
+ false
+ Library
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+ ..\..\..\TechnitiumLibrary\bin\TechnitiumLibrary.Net.dll
+ false
+
+
+
+
+
+ PreserveNewest
+
+
+
+
diff --git a/Apps/DropRequestsApp/dnsApp.config b/Apps/DropRequestsApp/dnsApp.config
new file mode 100644
index 00000000..b99eb82e
--- /dev/null
+++ b/Apps/DropRequestsApp/dnsApp.config
@@ -0,0 +1,33 @@
+{
+ "enableBlocking": true,
+ "allowedNetworks": [
+ "127.0.0.1",
+ "::1",
+ "10.0.0.0/8",
+ "172.16.0.0/12",
+ "192.168.0.0/16"
+ ],
+ "blockedNetworks": [
+ "1.1.1.1/24"
+ ],
+ "blockedQuestions": [
+ {
+ "name": "example.com"
+ },
+ {
+ "type": "ANY"
+ },
+ {
+ "name": "pizzaseo.com",
+ "type": "RRSIG"
+ },
+ {
+ "name": "sl",
+ "type": "ANY"
+ },
+ {
+ "name": "a.a.a.ooooops.space",
+ "type": "A"
+ }
+ ]
+}
\ No newline at end of file