diff --git a/Apps/WildIpApp/App.cs b/Apps/WildIpApp/App.cs
new file mode 100644
index 00000000..274a22bc
--- /dev/null
+++ b/Apps/WildIpApp/App.cs
@@ -0,0 +1,119 @@
+/*
+Technitium DNS Server
+Copyright (C) 2022 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 DnsServerCore.ApplicationCommon;
+using System;
+using System.Net;
+using System.Threading.Tasks;
+using TechnitiumLibrary.Net.Dns;
+using TechnitiumLibrary.Net.Dns.ResourceRecords;
+
+namespace WildIp
+{
+ public class App : IDnsApplication, IDnsAppRecordRequestHandler
+ {
+ #region IDisposable
+
+ public void Dispose()
+ {
+ //do nothing
+ }
+
+ #endregion
+
+ #region public
+
+ public Task InitializeAsync(IDnsServer dnsServer, string config)
+ {
+ //do nothing
+ return Task.CompletedTask;
+ }
+
+ public Task ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, string appRecordName, uint appRecordTtl, string appRecordData)
+ {
+ string qname = request.Question[0].Name;
+
+ if (qname.Length == appRecordName.Length)
+ return Task.FromResult(null);
+
+ DnsResourceRecord answer;
+
+ switch (request.Question[0].Type)
+ {
+ case DnsResourceRecordType.A:
+ {
+ string subdomain = qname.Substring(0, qname.Length - appRecordName.Length);
+ string[] parts = subdomain.Split(new char[] { '.', '-' }, StringSplitOptions.RemoveEmptyEntries);
+ byte[] rawIp = new byte[4];
+ int i = 0;
+
+ for (int j = 0; (j < parts.Length) && (i < 4); j++)
+ {
+ if (byte.TryParse(parts[j], out byte x))
+ rawIp[i++] = x;
+ }
+
+ if (i < 4)
+ return Task.FromResult(null);
+
+ IPAddress address = new IPAddress(rawIp);
+
+ answer = new DnsResourceRecord(request.Question[0].Name, DnsResourceRecordType.A, DnsClass.IN, appRecordTtl, new DnsARecordData(address));
+ }
+ break;
+
+ case DnsResourceRecordType.AAAA:
+ {
+ string subdomain = qname.Substring(0, qname.Length - appRecordName.Length - 1);
+ string[] parts = subdomain.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
+ IPAddress address = null;
+
+ foreach (string part in parts)
+ {
+ if (part.Contains('-') && IPAddress.TryParse(part.Replace('-', ':'), out address))
+ break;
+ }
+
+ if (address is null)
+ return Task.FromResult(null);
+
+ answer = new DnsResourceRecord(request.Question[0].Name, DnsResourceRecordType.AAAA, DnsClass.IN, appRecordTtl, new DnsAAAARecordData(address));
+ }
+ break;
+
+ default:
+ return Task.FromResult(null);
+ }
+
+ return Task.FromResult(new DnsDatagram(request.Identifier, true, request.OPCODE, true, false, request.RecursionDesired, isRecursionAllowed, false, false, DnsResponseCode.NoError, request.Question, new DnsResourceRecord[] { answer }));
+ }
+
+ #endregion
+
+ #region properties
+
+ public string Description
+ { get { return "Returns the IP address that was embedded in the subdomain name for A and AAAA queries. It works similar to sslip.io."; } }
+
+ public string ApplicationRecordDataTemplate
+ { get { return null; } }
+
+ #endregion
+ }
+}
diff --git a/Apps/WildIpApp/WildIpApp.csproj b/Apps/WildIpApp/WildIpApp.csproj
new file mode 100644
index 00000000..c026f7e8
--- /dev/null
+++ b/Apps/WildIpApp/WildIpApp.csproj
@@ -0,0 +1,38 @@
+
+
+
+ net6.0
+ false
+ true
+ 1.0
+ Technitium
+ Technitium DNS Server
+ Shreyas Zare
+ WildIpApp
+ WildIp
+ https://technitium.com/dns/
+ https://github.com/TechnitiumSoftware/DnsServer
+ false
+ Library
+
+
+
+
+ false
+
+
+
+
+
+ ..\..\..\TechnitiumLibrary\bin\TechnitiumLibrary.Net.dll
+ false
+
+
+
+
+
+ PreserveNewest
+
+
+
+
diff --git a/Apps/WildIpApp/dnsApp.config b/Apps/WildIpApp/dnsApp.config
new file mode 100644
index 00000000..7a2450c3
--- /dev/null
+++ b/Apps/WildIpApp/dnsApp.config
@@ -0,0 +1 @@
+#This app requires no config.
\ No newline at end of file
diff --git a/DnsServer.sln b/DnsServer.sln
index 82e3a9cc..5058e5ef 100644
--- a/DnsServer.sln
+++ b/DnsServer.sln
@@ -37,6 +37,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NxDomainApp", "Apps\NxDomai
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlockPageApp", "Apps\BlockPageApp\BlockPageApp.csproj", "{45C6F9AD-57D6-4D6D-9498-10B5C828E47E}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WildIpApp", "Apps\WildIpApp\WildIpApp.csproj", "{8B6BEB00-0AC2-4680-A848-31AD8A0FCD82}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -107,6 +109,10 @@ Global
{45C6F9AD-57D6-4D6D-9498-10B5C828E47E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{45C6F9AD-57D6-4D6D-9498-10B5C828E47E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{45C6F9AD-57D6-4D6D-9498-10B5C828E47E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8B6BEB00-0AC2-4680-A848-31AD8A0FCD82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8B6BEB00-0AC2-4680-A848-31AD8A0FCD82}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8B6BEB00-0AC2-4680-A848-31AD8A0FCD82}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8B6BEB00-0AC2-4680-A848-31AD8A0FCD82}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -123,6 +129,7 @@ Global
{A4C31093-CA65-42D4-928A-11907076C0DE} = {938BF8EF-74B9-4FE0-B46F-11EBB7A4B3D2}
{BB0010FC-20E9-4397-BF9B-C9955D9AD339} = {938BF8EF-74B9-4FE0-B46F-11EBB7A4B3D2}
{45C6F9AD-57D6-4D6D-9498-10B5C828E47E} = {938BF8EF-74B9-4FE0-B46F-11EBB7A4B3D2}
+ {8B6BEB00-0AC2-4680-A848-31AD8A0FCD82} = {938BF8EF-74B9-4FE0-B46F-11EBB7A4B3D2}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6747BB6D-2826-4356-A213-805FBCCF9201}