mirror of
https://github.com/fergalmoran/DnsServer.git
synced 2026-01-06 00:36:32 +00:00
138 lines
4.4 KiB
C#
138 lines
4.4 KiB
C#
/*
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
using DnsApplicationCommon;
|
|
using MaxMind.GeoIP2;
|
|
using MaxMind.GeoIP2.Responses;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Threading.Tasks;
|
|
using TechnitiumLibrary.Net.Dns;
|
|
using TechnitiumLibrary.Net.Dns.ResourceRecords;
|
|
|
|
namespace DefaultDnsApplication
|
|
{
|
|
public class GeoContinentCNAME : IDnsApplicationRequestHandler
|
|
{
|
|
#region variables
|
|
|
|
DatabaseReader _mmCountryReader;
|
|
|
|
#endregion
|
|
|
|
#region IDisposable
|
|
|
|
bool _disposed;
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (_disposed)
|
|
return;
|
|
|
|
if (disposing)
|
|
{
|
|
if (_mmCountryReader != null)
|
|
_mmCountryReader.Dispose();
|
|
}
|
|
|
|
_disposed = true;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region public
|
|
|
|
public Task InitializeAsync(IDnsServer dnsServer, string config)
|
|
{
|
|
if (_mmCountryReader == null)
|
|
{
|
|
string mmFile = Path.Combine(dnsServer.ApplicationFolder, "GeoIP2-Country.mmdb");
|
|
|
|
if (!File.Exists(mmFile))
|
|
mmFile = Path.Combine(dnsServer.ApplicationFolder, "GeoLite2-Country.mmdb");
|
|
|
|
if (!File.Exists(mmFile))
|
|
throw new FileNotFoundException("MaxMind Country file is missing!");
|
|
|
|
_mmCountryReader = new DatabaseReader(mmFile);
|
|
}
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task<DnsDatagram> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, string zoneName, uint appRecordTtl, string appRecordData, bool isRecursionAllowed, IDnsServer dnsServer)
|
|
{
|
|
string continent;
|
|
|
|
if (_mmCountryReader.TryCountry(remoteEP.Address, out CountryResponse response))
|
|
continent = response.Continent.Code;
|
|
else
|
|
continent = "default";
|
|
|
|
dynamic jsonAppRecordData = JsonConvert.DeserializeObject(appRecordData);
|
|
dynamic jsonCname = jsonAppRecordData[continent];
|
|
if (jsonCname != null)
|
|
{
|
|
string cname = jsonCname.Value;
|
|
if (!string.IsNullOrEmpty(cname))
|
|
{
|
|
IReadOnlyList<DnsResourceRecord> answers;
|
|
|
|
if (request.Question[0].Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase)) //check for zone apex
|
|
answers = new DnsResourceRecord[] { new DnsResourceRecord(request.Question[0].Name, DnsResourceRecordType.ANAME, DnsClass.IN, appRecordTtl, new DnsANAMERecord(cname)) }; //use ANAME
|
|
else
|
|
answers = new DnsResourceRecord[] { new DnsResourceRecord(request.Question[0].Name, DnsResourceRecordType.CNAME, DnsClass.IN, appRecordTtl, new DnsCNAMERecord(cname)) };
|
|
|
|
return Task.FromResult(new DnsDatagram(request.Identifier, true, request.OPCODE, true, false, request.RecursionDesired, isRecursionAllowed, false, false, DnsResponseCode.NoError, request.Question, answers));
|
|
}
|
|
}
|
|
|
|
return Task.FromResult<DnsDatagram>(null);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region properties
|
|
|
|
public string Description
|
|
{ get { return "Returns CNAME record based on the continent the client queries from using MaxMind GeoIP2 Country database. Note that the app will return ANAME record for an APP record at zone apex."; } }
|
|
|
|
public string ApplicationRecordDataTemplate
|
|
{
|
|
get
|
|
{
|
|
return @"{
|
|
""EU"": ""eu.example.com"",
|
|
""default"": ""example.com""
|
|
}";
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|