diff --git a/DnsApplicationCommon/IDnsLogger.cs b/DnsApplicationCommon/IDnsLogger.cs new file mode 100644 index 00000000..9a14d0c3 --- /dev/null +++ b/DnsApplicationCommon/IDnsLogger.cs @@ -0,0 +1,244 @@ +/* +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 System; +using System.Collections.Generic; +using System.Net; +using System.Threading.Tasks; +using TechnitiumLibrary.Net.Dns; + +namespace DnsApplicationCommon +{ + public enum DnsServerResponseType : byte + { + Authoritative = 1, + Recursive = 2, + Cached = 3, + Blocked = 4 + } + + /// + /// Allows a DNS App to log incoming DNS requests and their corresponding responses. + /// + public interface IDnsLogger : IDisposable + { + /// + /// Allows initializing the DNS application with a config. This function is also called when the config is updated to allow reloading. + /// + /// The DNS server interface object that allows access to DNS server properties. + /// The DNS application config stored in the dnsApp.config file. + Task InitializeAsync(IDnsServer dnsServer, string config); + + /// + /// Allows a DNS App to log incoming DNS requests and responses. This method is called by the DNS Server after an incoming request is processed and a response is sent. + /// + /// The incoming DNS request that was received. + /// The end point (IP address and port) of the client making the request. + /// The protocol using which the request was received. + /// The DNS response that was sent. + Task InsertLogAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, DnsDatagram response); + + /// + /// Allows DNS Server HTTP API to query the logs recorded by the DNS App. + /// + /// The page number to be displayed to the user. + /// Total entries per page. + /// Optional parameter to filter records by start date time. + /// Optional parameter to filter records by end date time. + /// Optional parameter to filter records by the client IP address. + /// Optional parameter to filter records by the DNS transport protocol. + /// Optional parameter to filter records by the type of response. + /// Optional parameter to filter records by the response code. + /// Optional parameter to filter records by the request QNAME. + /// Optional parameter to filter records by the request QTYPE. + /// Optional parameter to filter records by the request QCLASS. + /// The DnsLogPage object that contains all the entries in the requested page number. + Task QueryLogsAsync(long pageNumber, int entriesPerPage, DateTime? start, DateTime? end, IPAddress clientIpAddress, DnsTransportProtocol? protocol, DnsServerResponseType? responseType, DnsResponseCode? rcode, string qname, DnsResourceRecordType? qtype, DnsClass? qclass); + + /// + /// The description about this app to be shown in the Apps section of the DNS web console. + /// + string Description { get; } + } + + public class DnsLogPage + { + #region variables + + readonly long _pageNumber; + readonly long _totalPages; + readonly long _totalEntries; + readonly IReadOnlyList _entries; + + #endregion + + #region constructor + + /// + /// Creates a new object initialized with all the log page parameters. + /// + /// The actual page number of the selected data set. + /// The total pages for the selected data set. + /// The total number of entries in the selected data set. + /// The DNS log entries in this page. + public DnsLogPage(long pageNumber, long totalPages, long totalEntries, IReadOnlyList entries) + { + _pageNumber = pageNumber; + _totalPages = totalPages; + _totalEntries = totalEntries; + _entries = entries; + } + + #endregion + + #region properties + + /// + /// The actual page number of the selected data set. + /// + public long PageNumber + { get { return _pageNumber; } } + + /// + /// The total pages for the selected data set. + /// + public long TotalPages + { get { return _totalPages; } } + + /// + /// The total number of entries in the selected data set. + /// + public long TotalEntries + { get { return _totalEntries; } } + + /// + /// The DNS log entries in this page. + /// + public IReadOnlyList Entries + { get { return _entries; } } + + #endregion + } + + public class DnsLogEntry + { + #region variables + + readonly long _rowNumber; + readonly DateTime _timestamp; + readonly IPAddress _clientIpAddress; + readonly DnsTransportProtocol _protocol; + readonly DnsServerResponseType _responseType; + readonly DnsResponseCode _rcode; + readonly DnsQuestionRecord _question; + readonly string _answer; + + #endregion + + #region constructor + + /// + /// Creates a new object initialized with all the log entry parameters. + /// + /// The row number of the entry in the selected data set. + /// The time stamp of the log entry. + /// The client IP address of the request. + /// The DNS transport protocol of the request. + /// The type of response sent by the DNS server. + /// The response code sent by the DNS server. + /// The question section in the request. + /// The answer in text format sent by the DNS server. + public DnsLogEntry(long rowNumber, DateTime timestamp, IPAddress clientIpAddress, DnsTransportProtocol protocol, DnsServerResponseType responseType, DnsResponseCode rcode, DnsQuestionRecord question, string answer) + { + _rowNumber = rowNumber; + _timestamp = timestamp; + _clientIpAddress = clientIpAddress; + _protocol = protocol; + _responseType = responseType; + _rcode = rcode; + _question = question; + _answer = answer; + + switch (_timestamp.Kind) + { + case DateTimeKind.Local: + _timestamp = _timestamp.ToUniversalTime(); + break; + + case DateTimeKind.Unspecified: + _timestamp = DateTime.SpecifyKind(_timestamp, DateTimeKind.Utc); + break; + } + } + + #endregion + + #region properties + + /// + /// The row number of the entry in the selected data set. + /// + public long RowNumber + { get { return _rowNumber; } } + + /// + /// The time stamp of the log entry. + /// + public DateTime Timestamp + { get { return _timestamp; } } + + /// + /// The client IP address of the request. + /// + public IPAddress ClientIpAddress + { get { return _clientIpAddress; } } + + /// + /// The DNS transport protocol of the request. + /// + public DnsTransportProtocol Protocol + { get { return _protocol; } } + + /// + /// The type of response sent by the DNS server. + /// + public DnsServerResponseType ResponseType + { get { return _responseType; } } + + /// + /// The response code sent by the DNS server. + /// + public DnsResponseCode RCODE + { get { return _rcode; } } + + /// + /// The question section in the request. + /// + public DnsQuestionRecord Question + { get { return _question; } } + + /// + /// The answer in text format sent by the DNS server. + /// + public string Answer + { get { return _answer; } } + + #endregion + } +}