📜 ⬆️ ⬇️

Dynamic DNS in C # and Yandex.API

Today, in addition to my favorite activity (messing with the Arduino in my circle of children's art), I decided to set up a server (Windows 2012 r2) and use it for various manipulations. Having studied a ton of information, everything went smoothly.

When I finished experimenting on a local network, I had a question: “How can I see my server from an external network if I have a dynamic IP”. The World Knowledge Book helped again and services such as DynDNS, no-ip, etc. were found.

After registering, I saw that I needed to download a program (there are no dyndns settings in the router), but as a conscientious paranoid, I don’t like to install third-party software. Remembering that I have a second-level domain with me delegated on Yandex, I began to study the side of the question to write my software in C #.

I took the article “Homemade Dynamic DNS” as a basis. The following method was written to send requests to the API:
')
static string GET(String getString) { HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(getString); request.Method = "GET"; String test = String.Empty; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { Stream dataStream = response.GetResponseStream(); StreamReader reader = new StreamReader(dataStream); test = reader.ReadToEnd(); reader.Close(); dataStream.Close(); } return test; } 

Now I had to somehow get an external IP, and since I decided not to use DynDNS at all, I decided not to contact the checkip.dyndns.org page. Began to look at the same Yandex. By sending a get-request to the yandex.com/internet page, I found an interesting line ipv4.internet.yandex.net/internet/api/v0/ip in response to such a request, I was given a beautiful IP in its purest form.

To understand where the token and id come from, please refer to the article I took as a basis. Thus formed the following lines:

  string ip = GET("http://ipv4.internet.yandex.net/internet/api/v0/ip").Trim('"'); string respons = GET("https://pddimp.yandex.ru/nsapi/edit_a_record.xml?token=" + token + "&domain=" + domain + " &subdomain=" + subdomain + "&record_id=" + id + "&content=" + ip); 

Finally, because This whole thing should work on the server, I decided to re-create the console application to the service. Timers and check for ip changes relative to the previous one were added.

 using System; using System.ServiceProcess; using System.IO; using System.Net; using System.Timers; namespace DDNSyapi { public partial class Service1 : ServiceBase { String outIp = ""; Timer timer1; public const string token = "YOURTOKEN"; public const string domain = "YOURDOMAIN"; public const string subdomain ="UPDATINGSUBDOMAIN"; public const string id = "id"; //take token on pddimp.yandex.ru/get_token.xml?domain_name=YOURDOMAIN //take id on pddimp.yandex.ru/nsapi/get_domain_records.xml?token=YOURTOKEN&domain=YOURDOMAIN public Service1() { InitializeComponent(); } public static void Logs(string err) { StreamWriter txtIst = new StreamWriter(System.IO.Path.GetDirectoryName( System.Environment.GetCommandLineArgs()[0]) + "//IpServerLog_" + DateTime.Now.Year + DateTime.Now.Month + DateTime.Now.Day + ".txt", true); txtIst.WriteLine(DateTime.Now.ToString("HH:mm:ss") + " : " + err); txtIst.Close(); } protected override void OnStart(string[] args) { timer1 = new System.Timers.Timer(30 * 60 * 1000); timer1.Elapsed += timer1_Tick; timer1.Start(); timer1.Enabled = true; Logs(" "); } private void timer1_Tick(object sender, EventArgs e) { timer1.Enabled = false; try { string ip = GET("http://ipv4.internet.yandex.net/internet/api/v0/ip").Trim('"'); if (!ip.Equals(outIp)) { outIp = ip; string respons = GET("https://pddimp.yandex.ru/nsapi/edit_a_record.xml?token=" + token + "&domain=" + domain + " &subdomain=" + subdomain + "&record_id=" + id + "&content=" + ip); Logs(respons); } } catch { Logs("  .."); } timer1.Enabled = true; } static string GET(String getString) { HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(getString); request.Method = "GET"; String test = String.Empty; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { Stream dataStream = response.GetResponseStream(); StreamReader reader = new StreamReader(dataStream); test = reader.ReadToEnd(); reader.Close(); dataStream.Close(); } return test; } protected override void OnStop() { timer1.Enabled = false; timer1.Stop(); timer1 = null; Logs(DateTime.Now.ToString("HH:mm:ss") + " - " + " "); } } } 

At the moment, when writing a new ip, there is a lot of mess in the log - you can either comment out at all after debugging, or you can parse on the Error error tag, then you can receive a clean response from the API. I did not do it, because IP changes very rarely, and when everything is debugged, API errors will rarely occur.

Thus, we take the external ip, we are no longer from a foreign resource, but from the same where we use the domain, the code can also be run on any windows machine, right up to the home computer. But then I advise you to redo the IP check, as the author did, to which I referred: he was advised to save the ip into a separate file and take the last one from it, compare it with the current one. I did not do this because my server has a rather high uptime and restarting the service will not clean the outIP variable very often.

That's all, I hope someone will benefit from this decision. Waiting for your comments and critics.

Source: https://habr.com/ru/post/310534/


All Articles