Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Приватный динамический IP – прийти, увидеть, утаить

Anna | 17.06.2014 | нет комментариев
Не задалось у меня общение с DynDNS сервисами дословно с первого дня знакомства. Грабли попадались на всяком шагу: регистрация, скачивание и запуск заказчика, настройка заказчика либо роутера – всюду были какие-то мелкие нюансы, недоговорки, недоделки либо легко баги, что приводило к неработоспособности обслуживания. В довесок ко каждому, через время «эти ребята» внезапно перестают быть белыми, мохнатыми и бесплатными — начинают слать спам, раз в месяц требовать разгадать капчу либо принуждают проделывать еще какие-либо телодвижения, Дабы подтвердить что ты еще жив. Всё это привело к всеобщей неприязни ко каждому сервисам сходственного рода. Так и появилась идея сделать что-то своё, и чтоб непременно «белое и мохнатое».

От идеи до реализации прошло достаточно много времени. В основном из-за непонимания «а что собственно мне нужно?». Читал статьи на досуге, кумекал, и понемногу возник в голове список основных требований к велосипеду.

Основные расположения.

Предназначение: узнать IP адрес удаленного компьютера (скажем домашний компьютер).
?рус паранойи: выше среднего! (то есть IP адрес обязаны знать только доверенные лица). Вот здесь как раз и основное различие, от сходственных сервисов – я не хочу Дабы всякий желающий мог получить адрес моего компьютера легко вбив в командной строке что-то типа «ping supercomp.dyndns.org».
Непременные данные «пушистости»:

  1. Бесплатность (не забываем что и время тоже деньги).
  2. Устойчивость.
  3. Простота готового решения для финального пользователя.

Исходя из уточнения к первому условию, спецтехнологии решено было применять только те, что лично мне больше-менее вестимы — Windows, c#, ASP.NET.
Под влиянием статьи «Свой примитивный DynDNS сервер» была предпринята попытка написания небольшого сайта-посредника. Но, посмотрев на удивительно стабильную не устойчивость бесплатных ASP.NET хостингов, от этой идеи было решено отказаться и в качестве посредников применять бесплатные почтовые сервисы и облачные хранилища. Кстати, именно из упомянутой статьи была взята, показавшаяся здоровой, идея с «вероятностью хранения IP адресов всех интерфейсов заказчика».
Вот как-то так и получилось, что это должно быть обыкновенное виндовое си-шарповое приложение.

Выбор «хранилища»

Под хранилищем подразумевается некое место, где будет лежать наша информация. Место это должно быть защищено от сторонних взоров, быть легкодоступно из всякий точки и непременно соответствовать трем «мохнатым» требованиям.
Дабы крепко не напрягаться, было решено остановиться на таких вариантах:

  • Файловая система компьютера (скажем папка синхронизируемая каким-нибудь облачным заказчиком) – сохранение либо чтение задач не вызывает безусловно, каждая работа с сетью лежит на заказчике облака.
  • Почта – отправляются письма без задач, а вот читать доводится через стороннюю бесплатную библиотеку.
  • Облачное хранилище (имеется ввиду взаимодействие с облаком без установки заказчика) – абсолютно осуществимо.

На третьем пункте остановимся, и разглядим допустимые варианты.
Заблаговременный опрос друзей и знакомых показывал, что множество ничего не имеют вопреки Яндекс-Диска и Скай-Драйва. Следственно они первоначально рассматривались как основные претенденты. Но проведя пол дня в «энергичном поиске», оказалось, что вдалеке не всякий облачный сервис предоставляет приписываемое средство взаимодействия. Скажем, Скай-Драйв API с некоторых пор немыслимо применять в настольных приложениях, Гугл-Драйв API – без бутылки не разобраться, а у ДропБокс – я как-то вообще не обнаружил SDK для Windows. Применение не официальных либо устаревших “API” даже не рассматривались, так как нет никакой ручательства что они завтра будут трудиться. Допустимо я нехорошо искал, либо не там и не то искал – не знаю, если у кого-то есть примеры, буду рад помощи. Последним гвоздём в загвоздку выбора облачного обслуживания, стал тот факт, что для работы с Яндекс-диском из c# не необходимы вообще никакие сторонние библиотеки.
На каком-то одном из этих 3 типов хранения/передачи останавливаться не стал. Было решено сделать поддержку всех трёх, а что определенно применять – оставить на выбор пользователя. Ибо обстановки бывают различные – у кого-то порты закрыты и почта не работает, кому-то невозможно ставить программы облачных заказчиков и т.д.

Всеобщий алгорифм работы приложения.

Всеобщий алгорифм работы примитивен как две копейки:

  1. Периодично сберегаем текстовые сообщения со каждой требуемой информацией в «хранилище»
  2. Периодично читаем сообщения, и показываем в комфортном виде.

Перейдем к реализации идей в программном коде.

Приобретение внешнего адреса.

Здесь все легко. В «интернетах» полно каждых сервисов, которые показывают ваш внешний адрес. Если немного теснее существующих, то сделать еще пару десятков не составит специального труда. Приблизительный код такой страницы на ASP.NET:

protected void Page_Load(object sender, EventArgs e)
{
	LabelIp.Text = HttpContext.Current.Request.UserHostAddress;
}

Возвратимся к нашему приложению. Применяя класс System.Net.WebClient скачиваем страничку с таким адресом в строку, разбираем её регулярным выражением и получаем надобную нам информацию:

WebClient webClient = new WebClient();
string strExternalIp = webClient.DownloadString("http://checkip.dyndns.org/");
strExternalIp = (new Regex(@"d{1,3}.d{1,3}.d{1,3}.d{1,3}")).Matches(strExternalIp)[0].ToString();
Приобретение свойств сетевых интерфесов.

В этом нам поможет класс System.Net.NetworkInformation.NetworkInterface, и его статический способ GetAllNetworkInterfaces(), тот, что возвращает массив элементов своего-же типа NetworkInterface[]. Перебрав данный массив мы можем получить из объекта IPInterfaceProperties всю необходимую нам информацию – IP адреса, маски, шлюзы, dns-сервера и т.д.:

NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
// перебираем все сетевые интерфейсы
foreach (NetworkInterface nic in adapters)
{
	string strInterfaceName = nic.Name;	// название интерфейса
	string strPhysicalAddress = nic.GetPhysicalAddress().ToString(); //МАС - адрес

	string strAddr = string.Empty;

	// перебираем IP адреса
	IPInterfaceProperties properties = nic.GetIPProperties();
	foreach (UnicastIPAddressInformation unicast in properties.UnicastAddresses)
	{
		strAddr = unicast.Address.ToString()   " / "   unicast.IPv4Mask;
	}
	// перебираем днс-сервера
	foreach (IPAddress dnsAddress in properties.DnsAddresses)
	{
		strAddr = dnsAddress.ToString();
	}
	// перебираем шлюзы
	foreach (GatewayIPAddressInformation gatewayIpAddressInformation in properties.GatewayAddresses)
	{
		strAddr = gatewayIpAddressInformation.Address.ToString();
	}
}
Передача текстового сообщения в «хранилище».

Собрав всю нужную информацию, отправляем её в «хранилище» в виде обыкновенного текстового файла (в случае с почтой – легко сообщение).
С обыкновенными файлами всё легко:

System.IO.File.WriteAllText("MyInterfaces.txt", strInterfaces);

С почтой тоже всё решается парой строк кода (способ запросто находится в интернете). Одна из допустимых вариаций:

MailMessage mail = new MailMessage
{
	From = new MailAddress(strMailAddress), // от кого
	Subject = strSubject,	// тема письма
	Body = strBody,			// тело письма
	IsBodyHtml = false
};
mail.To.Add(new MailAddress(Settings.Default.strMailTo)); // кому

SmtpClient client = new SmtpClient
{
	Host = strSmtpServer, // адрес SMTP сервера
	Port = nSmtpServerPort,	// порт SMTP сервера
	EnableSsl = isSmtpSsl,	// необходимо ли испльзовать SSL
	Credentials = new NetworkCredential(strEmailUserName, strMailPassword), // логин пароль
	DeliveryMethod = SmtpDeliveryMethod.Network
};
client.Send(mail); // отправляем
mail.Dispose();

А вот с облаками немножко труднее, всеобщий толк – сделать верный веб запрос в тот, что впихнуть передаваемый текст:

// strFilePath - имя и путь к файлу на сервере
HttpWebRequest web = (HttpWebRequest)WebRequest.Create("https://webdav.yandex.ru/"   strFilePath);
// указываем логин и пароль (двукратно!!! в различных местах)
web.Credentials = new NetworkCredential("mail@yandex.ru", "password");
web.Headers.Add("Authorization: Basic "   Convert.ToBase64String(Encoding.Unicode.GetBytes("mail@yandex.ru"   ":"   "password")));
web.Accept = "*/*";
web.Method = "PUT";
web.ContentType = "application/binary";
web.ContentLength = buffer.Length;
using (Stream myReqStream = web.GetRequestStream())
{
	// strContent - текст передаваемого файла
	byte[] buffer = Encoding.UTF8.GetBytes(strContent); 
	myReqStream.Write(buffer, 0, buffer.Length);
	myReqStream.Flush();
}
HttpWebResponse resp = (HttpWebResponse)web.GetResponse();

Тут немножко пришлось поплясать с кодировками, но способом «научного тыка» было установлено, что с UTF8 всё отменно раk! С первым всё легко – обыкновенный список и пару колонок. А вот со вторым труднее. Реализовать дозволено двумя путями:

  1. Редактирование файла %windir%system32driversetchosts
  2. Сделать свой локальный DNS сервер

Первое реализуется достаточно легко, файл hosts – это обыкновенный текстовый файл, тот, что без труда читается/изменяется/сохраняется, основное только иметь на это права. А их то у обыкновенного пользователя нет, следственно повышаем у нашего приложения «ярус управления учетными записями Windows» поставив в файле app.manifest значение для requestedExecutionLevel = requireAdministrator. Подробнее об этом дозволено прочитать тут. Трудимся с файлом хостов примерно так:

//открываем файл хостов
string strHosts = File.ReadAllText(Environment.SystemDirectory   "\drivers\etc\hosts");
string[] linesHostsOld = Regex.Split(strHosts, "rn|r|n"); // разбиваем на строки
StringBuilder sbHostsNew = new StringBuilder();
// обрабатываем все строки
foreach (string lineHosts in linesHostsOld)
{
    sbHostsNew.AppendLine(lineHosts);
}
// добавляем в конец нынешние значения хостов
sbHostsNew.AppendLine("127.0.0.1  hello.world.com");
// сберегаем файл хостов
File.WriteAllText(Environment.SystemDirectory   "\drivers\etc\hosts", sbHostsNew.ToString());

2-й вариант у меня не удалось отлично оттестировать, так-как всех пока-что всецело устраивает работоспособность первого способа. DNS сервер реализован помощи сторонней библиотеки «ARSoft.Tools.Net». Крепко не мудрим, и по этим примерам делаем свои функции, примерно так:

DnsServer _server = new DnsServer(IPAddress.Any, 10, 10, ProcessQuery);
_server.Start(); // запуск сервера

// запрос адреса у DNS сервера
private static DnsMessageBase ProcessQuery(
	DnsMessageBase message, 
	IPAddress clientAddress, 
	ProtocolType protocol)
{
	message.IsQuery = false;
	DnsMessage query = message as DnsMessage;

	if (query != null)
	{
		if (query.Questions.Count == 1)
		{
			if (query.Questions[0].RecordType == RecordType.A)
			{
				if (query.Questions[0].Name.Equals("hello.world.com", StringComparison.InvariantCultureIgnoreCase))
				{
					IPAddress ip;
					if (IPAddress.TryParse("127.0.0.1", out ip))
					{
						query.ReturnCode = ReturnCode.NoError;
						DnsRecordBase rec = new ARecord(strHostName, 0, ip);
						query.AnswerRecords.Add(rec);
						return message;
					}
				}
			}
		}
	}
	message.ReturnCode = ReturnCode.ServerFailure;
	return message;
} 

Готовое приложение.

Собрав совместно всё выше описанное, и добавив вызов надобных процедур по таймеру, получится некое подобие задуманной программы. Остается только доработать всё напильником, привести в божеский вид и дозволено показывать людям.
Все настройки (а их получилось не немного) приложение хранит в файле %PROGRAM_NAME%.exe.config а сам файл лежит где то в этом районе: %USERPROFILE%AppDataLocal%PROGRAM_NAME%***. Реализовано это при помощи стандартных вероятностей Properties.Settings.Default. Пароли хранятся там-же, но в зашифрованном виде. Шифрование сделано применяя DPAPI (на харбе по этой теме есть статья и вопрос).
Работу с настройками формы, с шифрованием, с таймерами, с параллельными процессами и каждого прочего, что не касается первоначальной темы я детально описывать не буду. Кому дюже увлекательно – неизменно дозволено посмотреть начальный код.

Внешний вид получившегося велосипеда:
Четыре скриншота программы




При первом запуске потребуется наблюдательно настроить все надобные параметры.
В минимальном варианте: на первом компьютере (с динамическим адресом) необходимо будет настроить «интерфейсы», а на втором компьютере (на котором нам необходимо знать динамический адрес) необходимо будет наблюдательно настроить «хосты».

Планыпо становлению.

  • Увеличение поддерживаемых облачных хранилищ.
  • Увеличение поддерживаемых почтовых протоколов
  • Шифрование передаваемой информации.

Начальный код плана и саму программу пока выложил на Яндекс.Диск.
Исходники дозволено скачать тут: http://yadi.sk/d/iZNy9wA28E0-E
Бинарные файлы лежат здесь: http://yadi.sk/d/kYpZIqdn8E-ui

На этом всё. Спасибо за внимание.

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB