|
@@ -1,6 +1,7 @@
|
|
using System;
|
|
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Generic;
|
|
|
|
+using System.Collections.ObjectModel;
|
|
using System.IO;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Net;
|
|
@@ -9,39 +10,44 @@ using System.Text;
|
|
|
|
|
|
namespace DnsForwarder
|
|
namespace DnsForwarder
|
|
{
|
|
{
|
|
- internal class Program : ProgramRev1
|
|
|
|
|
|
+ internal class Program
|
|
{
|
|
{
|
|
- private static Socket Listener;
|
|
|
|
- private static BlockingCollection<string> ConsoleOutout;
|
|
|
|
|
|
+ private static string _defaultDns;
|
|
|
|
+ private static string _cnDns;
|
|
|
|
+ private static IReadOnlyDictionary<string, int> _chinaList;
|
|
|
|
+ private static string[] _chinaListDns;
|
|
|
|
+
|
|
|
|
+ private static Socket _listener;
|
|
|
|
+ private static BlockingCollection<string> _consoleOutout;
|
|
|
|
|
|
private static void Main(string[] args)
|
|
private static void Main(string[] args)
|
|
{
|
|
{
|
|
if (args.Length != 3)
|
|
if (args.Length != 3)
|
|
{
|
|
{
|
|
- Console.WriteLine("<default dns server ip> <china dns server ip> <path to dnsmasq-china-list file>");
|
|
|
|
|
|
+ Console.WriteLine("<default dns server ip> <.CN dns server ip> <path to dnsmasq-china-list file>");
|
|
Environment.Exit(-1);
|
|
Environment.Exit(-1);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
Console.WriteLine("Starting...");
|
|
Console.WriteLine("Starting...");
|
|
- Console.WriteLine($"Default Server:{DefaultServer = args[0]}");
|
|
|
|
- Console.WriteLine($"China DNS Server:{ChinaServer = args[1]}");
|
|
|
|
|
|
+ Console.WriteLine($"Default Server:{_defaultDns = args[0]}");
|
|
|
|
+ Console.WriteLine($"China DNS Server:{_cnDns = args[1]}");
|
|
Console.WriteLine($"dnsmasq-china-list file:{args[2]}");
|
|
Console.WriteLine($"dnsmasq-china-list file:{args[2]}");
|
|
|
|
|
|
Console.WriteLine("Loading list file...");
|
|
Console.WriteLine("Loading list file...");
|
|
- ChinaList = LoadListFile(args[2]).ToDictionary(p => p[0], p => p[1]);
|
|
|
|
|
|
+ LoadListFile(args[2]);
|
|
Console.WriteLine("OK. Listening...");
|
|
Console.WriteLine("OK. Listening...");
|
|
|
|
|
|
- Listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
|
|
|
- Listener.Bind(new IPEndPoint(IPAddress.Any, 53));
|
|
|
|
|
|
+ _listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
|
|
|
+ _listener.Bind(new IPEndPoint(IPAddress.Any, 53));
|
|
|
|
|
|
- ConsoleOutout = new BlockingCollection<string>();
|
|
|
|
|
|
+ _consoleOutout = new BlockingCollection<string>();
|
|
|
|
|
|
StartHandleRequest();
|
|
StartHandleRequest();
|
|
|
|
|
|
while (true)
|
|
while (true)
|
|
{
|
|
{
|
|
- Console.WriteLine(ConsoleOutout.Take());
|
|
|
|
|
|
+ Console.WriteLine(_consoleOutout.Take());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -49,13 +55,13 @@ namespace DnsForwarder
|
|
{
|
|
{
|
|
var buf = new byte[1500];
|
|
var buf = new byte[1500];
|
|
EndPoint from = new IPEndPoint(IPAddress.Any, 0);
|
|
EndPoint from = new IPEndPoint(IPAddress.Any, 0);
|
|
- Listener.BeginReceiveFrom(buf, 0, buf.Length, SocketFlags.None, ref from, Callback, buf);
|
|
|
|
|
|
+ _listener.BeginReceiveFrom(buf, 0, buf.Length, SocketFlags.None, ref from, Callback, buf);
|
|
}
|
|
}
|
|
|
|
|
|
private static void Callback(IAsyncResult ar)
|
|
private static void Callback(IAsyncResult ar)
|
|
{
|
|
{
|
|
EndPoint from = new IPEndPoint(IPAddress.Any, 0);
|
|
EndPoint from = new IPEndPoint(IPAddress.Any, 0);
|
|
- var count = Listener.EndReceiveFrom(ar, ref from);
|
|
|
|
|
|
+ var count = _listener.EndReceiveFrom(ar, ref from);
|
|
var buf = (byte[])ar.AsyncState;
|
|
var buf = (byte[])ar.AsyncState;
|
|
|
|
|
|
StartHandleRequest();
|
|
StartHandleRequest();
|
|
@@ -64,53 +70,10 @@ namespace DnsForwarder
|
|
|
|
|
|
var target = MatchServer(domain);
|
|
var target = MatchServer(domain);
|
|
|
|
|
|
- ConsoleOutout.Add($"{DateTime.Now:yyyyMMdd HH:mm:ss} {from} [{target}]\t{domain}");
|
|
|
|
|
|
+ _consoleOutout.Add($"{DateTime.Now:yyyyMMdd HH:mm:ss} {from} [{target}]\t{domain}");
|
|
|
|
|
|
- Listener.SendTo(GetDnsResponse(buf, count, target), from);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- internal class ProgramRev1
|
|
|
|
- {
|
|
|
|
- protected static string DefaultServer;
|
|
|
|
- protected static string ChinaServer;
|
|
|
|
- protected static Dictionary<string, string> ChinaList;
|
|
|
|
-
|
|
|
|
- private static void MainRev1(string[] args)
|
|
|
|
- {
|
|
|
|
- if (args.Length != 3)
|
|
|
|
- {
|
|
|
|
- Console.WriteLine("<default dns server ip> <china dns server ip> <path to dnsmasq-china-list file>");
|
|
|
|
- Environment.Exit(-1);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- Console.WriteLine("Starting...");
|
|
|
|
- Console.WriteLine($"Default Server:{DefaultServer = args[0]}");
|
|
|
|
- Console.WriteLine($"China DNS Server:{ChinaServer = args[1]}");
|
|
|
|
- Console.WriteLine($"dnsmasq-china-list file:{args[2]}");
|
|
|
|
-
|
|
|
|
- Console.WriteLine("Loading list file...");
|
|
|
|
- ChinaList = LoadListFile(args[2]).ToDictionary(p => p[0], p => p[1]);
|
|
|
|
-
|
|
|
|
- Console.WriteLine("OK. Listing...");
|
|
|
|
-
|
|
|
|
- var listen = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
|
|
|
- listen.Bind(new IPEndPoint(IPAddress.Any, 53));
|
|
|
|
-
|
|
|
|
- while (true)
|
|
|
|
- {
|
|
|
|
- EndPoint inEp = new IPEndPoint(IPAddress.Any, 0);
|
|
|
|
- var buf = new byte[1500];
|
|
|
|
- var count = listen.ReceiveFrom(buf, 0, buf.Length, SocketFlags.None, ref inEp);
|
|
|
|
- var domain = ExtractDomainName(buf, count);
|
|
|
|
-
|
|
|
|
- var target = MatchServer(domain);
|
|
|
|
-
|
|
|
|
- Console.WriteLine($"{DateTime.Now:yyyyMMdd HH:mm:ss} {inEp} [{target}]\t{domain}");
|
|
|
|
-
|
|
|
|
- listen.SendTo(GetDnsResponse(buf, count, target), inEp);
|
|
|
|
- }
|
|
|
|
|
|
+ var dnsResponse = GetDnsResponse(buf, count, target);
|
|
|
|
+ if (dnsResponse != null) _listener.SendTo(dnsResponse, from);
|
|
}
|
|
}
|
|
|
|
|
|
protected static string ExtractDomainName(byte[] buf, int count)
|
|
protected static string ExtractDomainName(byte[] buf, int count)
|
|
@@ -143,36 +106,67 @@ namespace DnsForwarder
|
|
using var to = new UdpClient();
|
|
using var to = new UdpClient();
|
|
to.Connect(host, 53);
|
|
to.Connect(host, 53);
|
|
to.Send(buf, count);
|
|
to.Send(buf, count);
|
|
- IPEndPoint outEp = null;
|
|
|
|
- return to.Receive(ref outEp); //TODO: Handle Upstream TimeOut
|
|
|
|
|
|
+
|
|
|
|
+ //Handle Upstream TimeOut
|
|
|
|
+
|
|
|
|
+ var asyncResult = to.BeginReceive(null, null);
|
|
|
|
+ asyncResult.AsyncWaitHandle.WaitOne(2000);
|
|
|
|
+ if (asyncResult.IsCompleted)
|
|
|
|
+ {
|
|
|
|
+ IPEndPoint remoteEP = null;
|
|
|
|
+ byte[] receivedData = to.EndReceive(asyncResult, ref remoteEP);
|
|
|
|
+ return receivedData;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return null;
|
|
}
|
|
}
|
|
|
|
|
|
protected static string MatchServer(string domain)
|
|
protected static string MatchServer(string domain)
|
|
{
|
|
{
|
|
var lower = domain.ToLower();
|
|
var lower = domain.ToLower();
|
|
- if (lower.EndsWith(".cn")) return ChinaServer;
|
|
|
|
|
|
+ if (lower.EndsWith(".cn")) return _cnDns;
|
|
|
|
|
|
var parts = lower.Split('.').Reverse().ToArray();
|
|
var parts = lower.Split('.').Reverse().ToArray();
|
|
|
|
|
|
for (int i = parts.Length - 1; i >= 0; i--)
|
|
for (int i = parts.Length - 1; i >= 0; i--)
|
|
{
|
|
{
|
|
var d = string.Join(".", parts.Take(i + 1).Reverse());
|
|
var d = string.Join(".", parts.Take(i + 1).Reverse());
|
|
- if (ChinaList.TryGetValue(d, out var tar)) return tar;
|
|
|
|
|
|
+ if (_chinaList.TryGetValue(d, out var tar)) return _chinaListDns[tar];
|
|
}
|
|
}
|
|
|
|
|
|
- return DefaultServer;
|
|
|
|
|
|
+ return _defaultDns;
|
|
}
|
|
}
|
|
|
|
|
|
- protected static string[][] LoadListFile(string path)
|
|
|
|
|
|
+ protected static void LoadListFile(params string[] paths)
|
|
{
|
|
{
|
|
- var lines = File.ReadAllLines(path);
|
|
|
|
- var items = lines.Select(p =>
|
|
|
|
|
|
+ var lines = paths.SelectMany(File.ReadAllLines);
|
|
|
|
+
|
|
|
|
+ var dic = new Dictionary<string, int>();
|
|
|
|
+ var tar = new List<string>();
|
|
|
|
+
|
|
|
|
+ foreach (var line in lines)
|
|
{
|
|
{
|
|
- if (p.StartsWith("#")) return null;
|
|
|
|
|
|
+ var p = line.Trim();
|
|
|
|
+ if (p.StartsWith("#")) continue;
|
|
|
|
+
|
|
var parts = p.Split('/');
|
|
var parts = p.Split('/');
|
|
- return new[] { parts[1], parts[2] };
|
|
|
|
- }).Where(p => p != null).ToArray();
|
|
|
|
- return items;
|
|
|
|
|
|
+ if (parts.Length != 3 && parts[0] != "server=") continue;
|
|
|
|
+
|
|
|
|
+ var domain = parts[1];
|
|
|
|
+ var dns = parts[2];
|
|
|
|
+
|
|
|
|
+ var dnsIndex = tar.IndexOf(dns);
|
|
|
|
+ if (dnsIndex == -1)
|
|
|
|
+ {
|
|
|
|
+ tar.Add(dns);
|
|
|
|
+ dnsIndex = tar.Count - 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dic[domain] = dnsIndex;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _chinaListDns = tar.ToArray();
|
|
|
|
+ _chinaList = new ReadOnlyDictionary<string, int>(dic);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|