Thứ Bảy, 20 tháng 7, 2019

IP động riêng - đến, xem, ẩn

Đăng Bởi: Admin - tháng 7 20, 2019 - 0 Bình Luận

https://c-sharp-asp-snippets.blogspot.com/2015/03/ip.html

Tôi không phải giao tiếp với các dịch vụ DynDNS ngay từ ngày đầu làm quen. Cái cào xuất hiện ở mọi bước: đăng ký, tải xuống và khởi chạy ứng dụng khách, thiết lập máy khách hoặc bộ định tuyến - ở mọi nơi đều có một số sắc thái nhỏ, hiểu lầm, thiếu sót hoặc chỉ là lỗi, dẫn đến sự không hoạt động của dịch vụ. Sau đó, trong phần phụ lục của mọi thứ, sau đó, những người này đột nhiên không còn trắng trẻo, mịn màng và tự do - họ bắt đầu gửi thư rác, một lần nữa họ yêu cầu giải captcha hoặc họ buộc họ phải thực hiện một số chuyển động khác để chứng minh rằng bạn vẫn còn sống. Tất cả điều này dẫn đến sự không thích chung cho tất cả các dịch vụ thuộc loại này. Và thế là ý tưởng nảy sinh để tạo ra một thứ gì đó của riêng họ, và do đó, phải có màu trắng và lông mịn.

Rất nhiều thời gian từ ý tưởng để thực hiện. Chủ yếu là do sự hiểu lầm về những gì tôi thực sự cần? Tôi đọc các bài báo lúc rảnh rỗi, tôi nghĩ về nó, và dần dần một danh sách các yêu cầu cơ bản cho một chiếc xe đạp xuất hiện trong đầu tôi.

Các quy định chính.


Mục đích : tìm địa chỉ IP của máy tính từ xa (ví dụ: máy tính ở nhà). 
Mức độ hoang tưởng : trên trung bình! (tức là chỉ có đại diện được ủy quyền mới biết địa chỉ IP). Đây là điểm khác biệt chính so với các dịch vụ tương tự - Tôi không muốn ai lấy địa chỉ máy tính của mình chỉ bằng cách gõ một cái gì đó giống như ping ping supercomp.dyndns.org trên dòng lệnh. 
Các điều kiện bắt buộc của "lông tơ" :
  1. Miễn phí (đừng quên rằng thời gian cũng là tiền).
  2. Ổn định
  3. Đơn giản của quyết định sẵn sàng cho người dùng cuối.

Dựa trên việc làm rõ điều kiện đầu tiên, người ta quyết định chỉ sử dụng công nghệ mà những người mà cá nhân tôi biết ít nhiều - Windows, c #, ASP.NET. 
Bị ảnh hưởng bởi bài viết về Máy chủ DynDNS đơn giản của bạn , một nỗ lực đã được thực hiện để viết một trang web proxy nhỏ. Nhưng, nhìn vào sự mất ổn định đáng ngạc nhiên của dịch vụ lưu trữ ASP.NET miễn phí, người ta đã quyết định từ bỏ ý tưởng này và sử dụng các dịch vụ thư miễn phí và kho lưu trữ đám mây làm trung gian. Nhân tiện, chính từ bài báo đã đề cập, ý tưởng hợp lý với khả năng lưu trữ địa chỉ IP của tất cả các giao diện máy khách đã được thực hiện. 
Bằng cách nào đó đã xảy ra rằng đây phải là một ứng dụng Windows B-Sharpe thông thường.

Sự lựa chọn của "lưu trữ"


Dưới kho lưu trữ có nghĩa là một nơi mà thông tin của chúng tôi sẽ nằm. Nơi này cần được bảo vệ khỏi những con mắt tò mò, có thể dễ dàng tiếp cận từ bất kỳ điểm nào và phải tuân thủ ba yêu cầu "lông tơ". 
Để không quá căng thẳng, người ta đã quyết định tập trung vào các lựa chọn sau:
  • Hệ thống tệp của máy tính (ví dụ: thư mục được đồng bộ hóa bởi một số máy khách đám mây) - hoàn toàn không có lưu hoặc đọc các vấn đề, tất cả đều hoạt động với mạng nằm trên máy khách đám mây.
  • Thư - thư được gửi mà không có vấn đề, nhưng bạn phải đọc qua thư viện miễn phí của bên thứ ba.
  • Lưu trữ đám mây (có nghĩa là tương tác với đám mây mà không cần cài đặt máy khách) là khá khả thi.

Trên đoạn thứ ba, chúng tôi sẽ dừng lại, và xem xét các tùy chọn có thể.
Một cuộc khảo sát sơ bộ về bạn bè và người quen cho thấy hầu hết không có gì chống lại Yandex-Disk và Sky-Drive. Do đó, ban đầu họ được coi là ứng viên chính. Nhưng sau khi dành nửa ngày trong chương trình tìm kiếm tích cực của Google, hóa ra không phải dịch vụ đám mây nào cũng cung cấp phương tiện tương tác lành mạnh. Ví dụ: API Sky Drive không thể được sử dụng trong các ứng dụng máy tính để bàn trong một thời gian, API Google Drive không thể hiểu được nếu không có chai và tôi đã tìm thấy SDK Windows trong DropBox. Việc sử dụng API API không chính thức hoặc lỗi thời thậm chí không được xem xét, vì không có gì đảm bảo rằng chúng sẽ hoạt động vào ngày mai. Có lẽ tôi đã nhìn xấu, hoặc không ở đó hoặc không tìm kiếm - Tôi không biết nếu ai đó có ví dụ, tôi sẽ sẵn lòng giúp đỡ. Cái đinh cuối cùng trong vấn đề chọn dịch vụ đám mây là thực tế
Tôi đã không dừng lại ở một trong ba loại lưu trữ / chuyển giao này. Nó đã được quyết định để hỗ trợ cho cả ba và cụ thể là sử dụng cái gì - để lại sự lựa chọn của người dùng. Đối với các tình huống là khác nhau - ai đó có cổng đóng và thư không hoạt động, ai đó không thể cài đặt chương trình máy khách đám mây, v.v.

Các thuật toán tổng thể của ứng dụng.


Thuật toán chung của công việc rất đơn giản là hai kopeks:
  1. Định kỳ lưu tin nhắn văn bản với tất cả các thông tin cần thiết trong "kho lưu trữ"
  2. Định kỳ chúng tôi đọc tin nhắn, và chúng tôi hiển thị ở dạng thuận tiện.

Hãy để chúng tôi chuyển sang thực hiện các ý tưởng trong mã chương trình.

Lấy một địa chỉ bên ngoài.

Thật đơn giản. Trong "Internet" có đầy đủ tất cả các loại dịch vụ hiển thị địa chỉ bên ngoài của bạn. Nếu có một vài cái hiện có, thì việc tạo ra một vài chục sẽ không khó. Mã mẫu cho một trang như vậy trên ASP.NET:
protected void Page_Load(object sender, EventArgs e)
{
    LabelIp.Text = HttpContext.Current.Request.UserHostAddress;
}

Hãy trở lại ứng dụng của chúng tôi. Sử dụng lớp System.Net.WebClient, chúng tôi tải xuống một trang có địa chỉ như vậy thành một chuỗi, phân tích cú pháp bằng một biểu thức chính quy và nhận thông tin chúng tôi cần:
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();

Lấy các thuộc tính của giao diện mạng.

Lớp System.Net.NetworkIn information.NetworkInterface và phương thức tĩnh của nó GetAllNetworkInterfaces (), trả về một mảng các phần tử của loại NetworkInterface [] của chính nó, sẽ giúp chúng ta làm điều này. Sau khi đi qua mảng này, chúng ta có thể nhận được tất cả thông tin chúng ta cần từ đối tượng IPInterfaceProperIES - địa chỉ IP, mặt nạ, cổng, máy chủ dns, v.v .:
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();
    }
}

Gửi tin nhắn văn bản trong "kho".

Sau khi thu thập tất cả các thông tin cần thiết, chúng tôi gửi nó đến kho lưu trữ trên máy tính như một tệp văn bản thuần túy (trong trường hợp thư, chỉ là một tin nhắn). 
Với các tệp thông thường, mọi thứ đều đơn giản:
System.IO.File.WriteAllText("MyInterfaces.txt", strInterfaces);

Với gần như giống nhau tất cả được giải quyết một vài dòng mã (phương pháp dễ dàng  nằm  trên Internet). Một trong những biến thể có thể:
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();

Nhưng với những đám mây khó khăn hơn một chút, ý nghĩa chung là tạo ra yêu cầu web chính xác để nhồi nhét văn bản truyền đi:
// 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();

Ở đây tôi đã phải nhảy một chút với các bảng mã, nhưng nó đã được tìm thấy bởi phương pháp tyke khoa học của cuốn sách mà mọi thứ đều hoạt động tốt với UTF8.

Đọc tin nhắn từ "kho"

Các tệp thông thường từ một hệ thống tệp thông thường được đọc trong một dòng. Nhưng chúng tôi không chỉ cần một tệp và tên của nó có thể không được biết trước, vì vậy chúng tôi xem qua toàn bộ nội dung của thư mục, tìm tệp bằng mặt nạ được chỉ định và lần lượt xử lý chúng:
// просмотр всех файлов из указанной директории по указанной маске
var files = Directory.EnumerateFiles("путь к папке", "*.txt");
strFileNames = files as string[] ?? files.ToArray();
foreach (string strFileName in strFileNames)
{
    string message = File.ReadAllText(strFileName); // читаем содержимое файла
    // что-то делаем с прочитанным
}


Tôi đã phải mày mò đọc thư. Mã được làm sắc nét dưới thư Google, vì vậy nó có thể hoạt động không chính xác trên các thư khác. Chính Google Mail đã dẫn đến việc sử dụng máy chủ IMAP (hiện tại, hotmail không hỗ trợ giao thức này). Nhiều người khuyên nên sử dụng thư viện giả miễn phí (tôi sẽ không nêu tên), trong đó định kỳ trả lại tin nhắn thay vì nội dung thư. Nhưng điều này vi phạm trực tiếp "yêu cầu lông thứ hai" - tính ổn định và nếu bạn trả tiền, "lông mịn thứ nhất" - miễn phí. Do đó, tôi đã chọn một thư viện hoàn toàn miễn phí và hoạt động hoàn toàn, trong đó có hoạt động với các máy chủ IMAP - Thư MailSystem.NETTHER Ví dụ về việc sử dụng có thể được tìm thấy trên trang dự án, ở đây tôi sẽ đưa ra một đoạn mã nhỏ để nhận thư:
Imap4Client imap = new Imap4Client();
imap.ConnectSsl("imap.gmail.com", 993); // подключаемся
imap.Login("mail@google.com", "password");// авторизуемся
Mailbox inbox = imap.SelectMailbox("inbox");// получаем папку входящих
int[] nIdsUnread = inbox.Search("UNSEEN"); // получаем только непрочитанные
int nUnreadCount = nIdsUnread.Length; // узнаем количество непрочитанных
for (int i = 0; i < nUnreadCount; i++)
{
    int idx = nIdsUnread[i]; // получаем индекс письма в папке входящих
    // получаем текст сообщения
    Message message = inbox.Fetch.MessageObject(idx);
    // message.Subject - содержит тему письма
    // message.BodyText.Text - содержит текст письма
    // обрабатываем полученную информацию
}

Đây là cách bạn có thể đọc thư - chỉ mười dòng mã, nhưng họ kéo năm thư viện (DLL) vào thư mục chương trình, và sau đó bạn phải mang chúng đi khắp mọi nơi. 

Đọc tệp từ lưu trữ đám mây thậm chí còn dễ hơn gửi chúng ở đó:
// 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 = "GET";
HttpWebResponse resp = (HttpWebResponse)web.GetResponse();
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
    string text = sr.ReadToEnd();
    // text - теперь содержит в себе текстовое содержимое файла
}

Nhưng ví dụ này sẽ chỉ đọc một tệp và chúng ta cần đọc tất cả các tệp từ thư mục được chỉ định. Nhiệm vụ này được giải quyết bằng yêu cầu sơ bộ của danh sách tập tin. Máy chủ sẽ trả lại tệp XML cho chúng tôi và xem qua nội dung của các thẻ <d: displayname> chúng tôi sẽ nhận được một danh sách các tệp:
// strPath - путь к папке на сервере
HttpWebRequest web = (HttpWebRequest)WebRequest.Create("https://webdav.yandex.ru/" + strPath);
// указываем логин и пароль
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.Headers.Add("Depth: 1");
web.Method = "PROPFIND";
List<string> retValue = new List<string>(); // в этот список попадут все файлы из указанной паки
HttpWebResponse resp = (HttpWebResponse)web.GetResponse();
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
    // сервер возвращает XML файл. Разбираем его содержимое:
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(sr.ReadToEnd());

    XmlNodeList displaynames = xmlDoc.GetElementsByTagName("d:displayname");
    int nCount = displaynames.Count;
    for (int i = 1; i < nCount; i++)
    {
        retValue.Add(displaynames[i].InnerText);
    }
}

DNS

Sau khi nhận được tất cả thông tin từ kho lưu trữ, câu hỏi được đặt ra - phải làm gì tiếp theo? Và không có nhiều lựa chọn:
  1. Hiển thị cho người dùng mọi thứ nhận được một cách thuận tiện.
  2. Tổ chức khả năng truy cập máy tính từ xa theo tên

Với cái đầu tiên, mọi thứ đều đơn giản - một danh sách thông thường và một vài cột. Nhưng thứ hai là khó khăn hơn. Bạn có thể thực hiện theo hai cách:
  1. Chỉnh sửa tệp% Windir% \ system32 \ driver \ etc \ hosts
  2. Tạo máy chủ DNS cục bộ của bạn

Việc đầu tiên được thực hiện khá đơn giản, tệp máy chủ là một tệp văn bản đơn giản, dễ đọc / thay đổi / lưu, điều chính là chỉ có quyền đối với nó. Nhưng người dùng thông thường không có họ, vì vậy chúng tôi tăng Cấp độ quản lý tài khoản Windows Windows cho ứng dụng của chúng tôi bằng cách đặt giá trị cho RequestExecutLevel = notifyAd Administrator trong tệp app.manifest. Tìm hiểu thêm về điều này  ở đây .Chúng tôi làm việc với tệp máy chủ như thế này:
//открываем файл хостов
string strHosts = File.ReadAllText(Environment.SystemDirectory + "\\drivers\\etc\\hosts");
string[] linesHostsOld = Regex.Split(strHosts, "\r\n|\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());

Tùy chọn thứ hai tôi không quản lý để kiểm tra tốt, vì cho đến nay mọi người đều hoàn toàn hài lòng với hiệu suất của phương pháp đầu tiên. Máy chủ DNS được triển khai bằng thư viện của bên thứ ba "ARSoft.Tools.Net ". Hoàn toàn không khôn ngoan, và  những ví dụ này  làm cho các chức năng của chúng ta, đại loại như thế này:
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;
} 

Ứng dụng đã sẵn sàng.


Bằng cách tập hợp tất cả những điều trên và thêm một cuộc gọi vào các thủ tục cần thiết trên đồng hồ bấm giờ, bạn sẽ có được một loại chương trình được hình thành. Nó chỉ còn để sửa đổi tất cả các tập tin, mang lại hình thức thiêng liêng và có thể được hiển thị cho mọi người. 
Tất cả các cài đặt (và hóa ra khá ít) được lưu trữ trong tệp% PROGRAM_NAME% .exe.config và chính tệp đó nằm ở đâu đó trong khu vực:% USERPROFILE% \ AppData \ Local \% PROGRAM_NAME% \ ***. Điều này được thực hiện bằng các tính năng tiêu chuẩn của Properties.Sinstall.Default Mật khẩu được lưu trữ ở đó, nhưng ở dạng mã hóa. Mã hóa được thực hiện bằng  DPAPI  (có một bài viết  và một  câu hỏi trên đĩa cứng về chủ đề này  ).
Tôi sẽ không mô tả chi tiết công việc với các cài đặt của biểu mẫu, với mã hóa, với bộ hẹn giờ, với các quy trình song song và mọi thứ khác không liên quan đến chủ đề ban đầu. Ai rất thú vị - bạn luôn có thể xem mã nguồn.

Sự xuất hiện của chiếc xe đạp kết quả:


Bốn ảnh chụp màn hình của chương trình





Khi bạn lần đầu tiên bắt đầu, bạn sẽ cần phải cấu hình cẩn thận tất cả các tham số cần thiết. 
Trong phiên bản tối thiểu: trên máy tính đầu tiên (có địa chỉ động), bạn sẽ cần định cấu hình "giao diện" và trên máy tính thứ hai (trên đó chúng tôi cần biết địa chỉ động), bạn sẽ cần định cấu hình cẩn thận "máy chủ".

Kế hoạch phát triển.


  • Tăng lưu trữ đám mây được hỗ trợ.
  • Tăng các giao thức thư được hỗ trợ
  • Mã hóa thông tin truyền đi.


Mã nguồn của dự án và bản thân chương trình vẫn chưa được tải lên Yandex.Disk. 
Các nguồn có thể được tải xuống ở đây:  http://yadi.sk/d/iZNy9wA28E0-E 
Các tệp nhị phân có tại đây:  http://yadi.sk/d/kYpZIqdn8E-ui

Phản Hồi Độc Giả

Một số lưu ý khi bình luận

Mọi bình luận sai nội quy sẽ bị xóa mà không cần báo trước (xem nội quy)

Bấm Thông báo cho tôi bên dưới khung bình luận để nhận thông báo khi admin trả lời

Để bình luận một đoạn code, hãy mã hóa code trước nhé