From 18b275b01cac16dd9d87b0b0f112e37e85fbeaf5 Mon Sep 17 00:00:00 2001 From: Shreyas Zare Date: Sat, 11 Sep 2021 16:28:16 +0530 Subject: [PATCH] DropRequestsApp: added new app --- Apps/DropRequestsApp/App.cs | 192 ++++++++++++++++++++ Apps/DropRequestsApp/DropRequestsApp.csproj | 41 +++++ Apps/DropRequestsApp/dnsApp.config | 33 ++++ 3 files changed, 266 insertions(+) create mode 100644 Apps/DropRequestsApp/App.cs create mode 100644 Apps/DropRequestsApp/DropRequestsApp.csproj create mode 100644 Apps/DropRequestsApp/dnsApp.config 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