123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Net;
- using System.Net.Sockets;
- using System.Text;
- namespace DnsForwarder
- {
- internal class Program : ProgramRev1
- {
- private static Socket Listener;
- private static BlockingCollection<string> ConsoleOutout;
- private static void Main(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. Listening...");
- Listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
- Listener.Bind(new IPEndPoint(IPAddress.Any, 53));
- ConsoleOutout = new BlockingCollection<string>();
- StartHandleRequest();
- while (true)
- {
- Console.WriteLine(ConsoleOutout.Take());
- }
- }
- private static void StartHandleRequest()
- {
- var buf = new byte[1500];
- EndPoint from = new IPEndPoint(IPAddress.Any, 0);
- Listener.BeginReceiveFrom(buf, 0, buf.Length, SocketFlags.None, ref from, Callback, buf);
- }
- private static void Callback(IAsyncResult ar)
- {
- EndPoint from = new IPEndPoint(IPAddress.Any, 0);
- var count = Listener.EndReceiveFrom(ar, ref from);
- var buf = (byte[])ar.AsyncState;
- StartHandleRequest();
- var domain = ExtractDomainName(buf, count);
- var target = MatchServer(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);
- }
- }
- protected static string ExtractDomainName(byte[] buf, int count)
- {
- var lst = new List<byte[]>();
- var ptr = 12;
- while (buf[ptr] != 0)
- {
- ptr += buf[ptr] + 1;
- }
- var bufDomain = new byte[ptr - 12];
- Array.Copy(buf, 12, bufDomain, 0, bufDomain.Length);
- //dot fill
- ptr = 0;
- while (ptr < bufDomain.Length)
- {
- var b = bufDomain[ptr];
- bufDomain[ptr] = (byte)'.';
- ptr += b + 1;
- }
- return Encoding.ASCII.GetString(bufDomain, 1, bufDomain.Length - 1);
- }
- protected static byte[] GetDnsResponse(byte[] buf, int count, string host, int port = 53)
- {
- using var to = new UdpClient();
- to.Connect(host, 53);
- to.Send(buf, count);
- IPEndPoint outEp = null;
- return to.Receive(ref outEp); //TODO: Handle Upstream TimeOut
- }
- protected static string MatchServer(string domain)
- {
- var lower = domain.ToLower();
- if (lower.EndsWith(".cn")) return ChinaServer;
- var parts = lower.Split('.').Reverse().ToArray();
- for (int i = parts.Length - 1; i >= 0; i--)
- {
- var d = string.Join(".", parts.Take(i + 1).Reverse());
- if (ChinaList.TryGetValue(d, out var tar)) return tar;
- }
- return DefaultServer;
- }
- protected static string[][] LoadListFile(string path)
- {
- var lines = File.ReadAllLines(path);
- var items = lines.Select(p =>
- {
- if (p.StartsWith("#")) return null;
- var parts = p.Split('/');
- return new[] { parts[1], parts[2] };
- }).Where(p => p != null).ToArray();
- return items;
- }
- }
- }
|