Сделать внутри программный аналог HOSTS

176
26 апреля 2018, 07:52

Есть необходимость в программе работать с сайтом, чье имя удалено из DNS. Работаю с помощью классов библиотеки System.Net, а именно HttpClient. При этом сайт отвергает запросы, в которых вместо имени хоста подставлен IP адрес, т.е. в запросе должно фигурировать именно имя хоста. Частичное решение моей проблемы - занесение нужной записи в файл Hosts, но мне нужно обеспечить:

  1. контроль за обращением к списку Ip адресов соответствующих имени
  2. работу в условиях отсутствия админских прав (т.е. невозможности редактировать hosts)

Вопрос: каким образом сделать так, чтоб внутри программы ресолвинг определенных имен перехватить и делать самому?

Answer 1

Имеется библиотека, которая позволяет создавать прокси DNS сервер в самом C# приложении, который может перехватывать все запросы и направлять их на нужные адреса. Здесь имеется пример создания прокси DNS сервера.

Приведу пример использования библиотеки:

class Program
{
    static DnsServer _proxyServer;
    static string _testDomain = "my.blablablakons.com";
    static string _redirectIp = "127.0.0.1";
    static string _realDnsServer = "8.8.8.8";
    static Task StartProxyServer()
    {
        // Proxy to google's DNS
        MasterFile masterFile = new MasterFile();
        // Resolve these domain to localhost
        //masterFile.AddIPAddressResourceRecord("blablablakons.com", _redirectIp);
        masterFile.AddIPAddressResourceRecord(_testDomain, "127.0.0.1");
        _proxyServer = new DnsServer(masterFile, _realDnsServer);
        // Log every request
        //_proxyServer.Requested += (request) => Console.WriteLine(request);
        _proxyServer.Responded += (request, response) => Console.WriteLine("{0} => {1}", request, response);
        //_proxyServer.Listening += () => Console.WriteLine("Listening started");
        //_proxyServer.Errored += (e) => {
        //    Console.WriteLine("Errored: {0}", e);
        //    ResponseException responseError = e as ResponseException;
        //    if (responseError != null) Console.WriteLine(responseError.Response);
        //};
        // Start the server (by default it listents on port 53)
        return _proxyServer.Listen();
    }

    static async void Do(object data)
    {
        CancellationToken token = (CancellationToken)data;
        HttpClient client = new HttpClient();
        client.Timeout = new TimeSpan(0, 0, 5);
        while (!token.IsCancellationRequested)
        {
            try
            {
                HttpResponseMessage response = await client.GetAsync(new Uri($"http://{_testDomain}"));
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex);
            }
            await Task.Delay(1000);
        }
    }

    static void Main(string[] args)
    {
        Task listenTask = StartProxyServer();
        // Start thread for send requests
        CancellationTokenSource cs = new CancellationTokenSource();
        Thread requestThr = new Thread(new ParameterizedThreadStart(Do));
        requestThr.Start(cs.Token);
        Console.WriteLine("All started");
        Console.ReadLine();
        cs.Cancel();
        requestThr.Join();
        _proxyServer.Dispose();
        listenTask.Wait();
    }
}

Суть работы примера:
1. Создается proxy-сервер, который публикуется на localhost по порту 53(порт по-умолчанию). При создании DNS сервера, основным(реальным) dns-сервером указываем адрес _realDnsServer(8.8.8.8). Те DNS имена, которые не будут найдены в нашем прокси DNS сервере, будут отправляться на этот указанный dns сервер
2. Прописываем для прокси сервера правило резолва требуемого DNS имени(_testDomain = "my.blablabla.com") на некий ip-адрес(_redirectIp = "127.0.0.1"), куда вы хотите отправлять запросы
3. В настройках операционной системы добавляем адрес нашего публикуемого прокси сервера (для простоты, я в настройках сетевого адаптера оставил один DNS адрес 127.0.0.1)
4. Все запросы к нашему DNS серверу логгируем _proxyServer.Requested += (request) => Console.WriteLine(request);
5. Запускаем поток, который раз в 1 секунду с помощью класса HttpClient делает GET запросы по DNS имени my.blablablakons.com.

Запускаем приложение.
Попытаемся открыть какую-нибудь страницу в браузере. При открытии страницы в браузере видим, что запрос по получению IP адреса открываемой страницы был проксирован через наш опубликованный сервер.
Попытаемся открыть страницу my.blablablakons.com. Видим отображение страницы, которую указали в резолве.

Таким образом, вы можете гибко из своего приложения управлять, на какие ip-адреса должны уходить ваши запросы, делая запрос по DNS-имени.

READ ALSO
Результат linq в ilist<Model>

Результат linq в ilist<Model>

Не могу выгрузить результат linq в Leads_SoucesОшибка CS0266 Не удается неявно преобразовать тип "System

187
Как удалить первую цифру из числа?

Как удалить первую цифру из числа?

У меня, например, есть число 2179, как я могу удалить цифру 2, чтобы получить 179 ?

168
Плагин криптопро не обрабатывает Transform urn://smev-gov-ru/xmldsig/transform

Плагин криптопро не обрабатывает Transform urn://smev-gov-ru/xmldsig/transform

Пытаюсь подписать запрос для отправки в СМЭВ шлюзУ меня есть пример запроса, где элемент Transforms имеет следующий вид:

235
wcf не могу найти pipe адрес

wcf не могу найти pipe адрес

Я начал изучать WCF и создал несколько тестовых http-сервисовТеперь я пытался создать службу WCF, используя привязку net

178