📜 ⬆️ ⬇️

Umpa-lumps Internet or how to program DNS

If you are administering networks and you need to manage a large, constantly changing number of servers, or if you are developing an application that uses dynamic load balancing, or if you deploy a multilingual website, you can’t get around the issues related to correct DNS setup.

As in any business, the Internet has its own invisible and inconspicuous workers, daily, hourly ... every millisecond performing their simple routine operations. These are of course routers, switches and other devices delivering data packets from one point to another. They have their own load adjusters, redirecting the flow in a different way in case of congestion. But how do they all know where to deliver these packages? A knowledgeable person will say - “this is where the IP address is indicated” and will be right. But the usual web surfer, as a rule, has no idea about IP addresses, but nevertheless several billions of simple web surfers successfully “surf” the Internet for themselves. Such an opportunity for them, and the “face” of the modern Internet, are determined by another “umpa-lump” - the DNS service.

Most users will never know about its existence, but that users, many system administrators, not to mention programmers, present its capabilities rather superficially. I think that I’m not mistaken if I say that “tough peppers” rarely use “advanced” techniques related to DNS. Meanwhile, many of the features provided by the domain name service are necessary elements when building highly reliable and scalable systems. The most famous of these features is load balancing and fault tolerance. More complex ones are geo-balancing, traffic routing. Yes, yes, it is routing using DNS tools, but we will not dwell on this now. We will start with simple things.


')
What can our DNS umpa lumps offer for load balancing? The most obvious and easily implemented way is the so-called round-robin balancing. It is based on the fact that you can add multiple A (or AAA) records in the DNS for the same name. After that, the DNS server will send them in turn, sending the client to one or another server. Setting up such balancing is easy using the domain control panel of any provider or DNS server. The task moves from the “administration” category to the “programming” category as soon as we need to add and remove servers to the farm automatically. For example, if it is an Amazon server and they have a dynamic address. And precisely, without writing scripts, it is impossible to cope with the task of ensuring failover.



To manage a DNS server, it must provide a specific API. The simplest "API" can be considered the nsupdate command, which is part of almost all * nix distributions and is included in cygwin under Windows. It can receive commands from a file, and accordingly, its work can be programmed by generating or preparing such a file with commands in advance. For example, to dynamically update server records, we can configure the use of TSIG in BIND and beyond:

# nsupdate -k keyfile filefile_commands
The key file looks like this:
 key domain.tld {
    algorithm hmac-md5;
    secret "PR3IxM1WocUm5uJ6- + yQeSmHbohhPR97K4RuNH2Vg7bYzM3R9Z27Li1w ==";
 }; 

File with commands like this:
     server 192.168.100.1
     zone domain.tld
     update delete server1.domain.tld 3600 A
     update add server1.domain.tld 3600 A 192.168.100.99
     send 

By the way, I use this technique to automatically register in my own, internal DNS of new servers created in Amazon.

Another type of DNS management API is the Dynamic Domain Name Services (DDNS) public services. Among them, EasyDNS, DynDNS, NameCheap, Zoneedit, etc. can be called. Those who are interested can pick up the sources of the universal update client ddclient and see in detail how it is implemented. All of these APIs are essentially protocols for accessing certain managed DNS servers to add / update / delete dynamic address records. DDNS services solve one simple task - to enable people with a dynamic address issued by the provider to find their computer by name. You register with the service, assign it to your computer in one of the proposed domains. Further in the client software, on your computer specify this name, registration name and password of the selected service. After that, the program independently determines your real IP address and registers the corresponding address record in the DNS service. When the provider changes the address, the program will automatically change it in the DNS service. This way you get a permanent name for a changing IP.

If you need full control over DNS, for example, if you are creating a complex, highly reliable distributed service or are a hosting provider and you need to dynamically redistribute the IP address space, there are full DNS management APIs: Dynect from DynDNS or PowerDNS Express from PowerDNS. I will focus on the first one - Dynect, since I have to work very closely with him in one of our projects.

Dynect is an API for managing DNS servers of Dynamic Network Services Inc. , known for its DynDNS trademark. I will refer to it as “Dyn”. DNS Dyn servers are located throughout the world and are represented in several data centers in each of the geographic regions (unfortunately, without Russia, but this does not create major problems). But at the same time, all of them (or a group, depending on rights) are managed as a whole through Dynect. This distribution provides a significant expansion of the capabilities of the name service in terms of reliability, geo-balancing and geo-targeting.

Dynect provides an almost complete set of calls for managing DNS and DDNS (including the DynDNS service) plus a rights demarcation system. The latter is important, as it allows you to cost various public services on the basis of Dynect and isolate the records and users within one or several domains. Functions are divided into groups:


A full list of features is presented on the DynDNS website and is available after registering as a partner or corporate client. Each of the functions has both a REST and a SOAP call. There is also experimental support for XML-RPC, but I have not tried it. My favorite way to call is SOAP / WSDL, since in this case I don’t need to manually describe the calls and perform the related operations to keep the call library up to date. I use Java as my programming language (and Netbeans environment), but on the Dyn website there are examples for other languages ​​as well.

Let's see how you can update the record using Dynect. Logically, we need to perform the following steps: register with Dynect (create session), update the record, post changes, exit (close the session). The code below is not complete. As on the one hand, the example is demo. On the other hand, the actual class of accessing Dynect is generated by Netbeans automatically from a WSDL file, and there is no need to edit such automatically generated code.

  public update () {
       try {
           if (userLogin (customerCode, userName, userPassword) {
               if (updateARecord (zone, fqdn, ip))
                  publishZone (zone);
           userLogout ();
           }
       } catch (ErrorResponse ex) {// exception handler
       }
    }

     / **
      * Sign up for DynDNS.  Registration independently handles 
      * exceptions.
      * @param customerCode
      * @param userName
      * @param userPassword
      * @return 
      * /
     public boolean userLogin (String customerCode, String userName, String userPassword) {
             SessionLoginRequestType sessionRequest;
             SessionLoginResponseType sessionResponse;
             boolean status;

         sessionRequest = new SessionLoginRequestType ();            
         sessionRequest.setUserName (userName);
         sessionRequest.setPassword (userPassword);
         ...
         try {
             sessionResponse = DynDNS.sessionLogin (sessionRequest);
             if (success.equalsIgnoreCase (sessionResponse.getStatus ())) {
                 loginData = sessionResponse.getData ();
                 status = true;
             } else {
                 status = false;
             }
         } catch (ErrorResponse ex) {
             status = false;
         }
         return status;
     }

     / **
      * Exit DynDNS
      * @throws ErrorResponse 
      * /
     public void userLogout () throws ErrorResponse {
             SessionLogoutRequestType logoutRequest = new SessionLogoutRequestType ();
             SessionLogoutResponseType logoutResponse;

         if (loginData! = null) {
             logoutRequest.setToken (loginData.getToken ());
             logoutResponse = DynDNS.sessionLogout (logoutRequest);            
         }
     }

   / **
      * Update Type A Record in DynDNS
      * @param zone
      * @param fqdn
      * @param ip
      * @return
      * @throws ErrorResponse 
      * /
     public boolean updateARecord (String zone, String fqdn, String ip) throws ErrorResponse {
             UpdateARecordRequestType request = new UpdateARecordRequestType ();
             UpdateARecordResponseType response;
             RDataA value = new RDataA ();
             boolean status;

         request.setToken (loginData.getToken ());
         request.setFqdn (fqdn);
         request.setZone (zone);
         value.setAddress (ip);
         request.setRdata (value);
         response = DynDNS.updateARecord (request);

         status = success.equalsIgnoreCase (response.getStatus ());
         return status;
     }

   / **
      * The function updates the zone in DynDNS - publishes changes to the DNS.
      * @param zone - updated zone
      * @return 
      * @throws api2.dynect.net.ErrorResponse
      * /
     public boolean publishZone (String zone) throws ErrorResponse {
             PublishZoneRequestType request;
             PublishZoneResponseType response;
             boolean status;

         request = new PublishZoneRequestType ();
         request.setToken (this.loginData.getToken ());
         request.setZone (zone);
         response = DynDNS.publishZone (request);
         status = success.equalsIgnoreCase (response.getStatus ());

         return status;
     } 

The attentive reader will notice that there is still some kind of customerCode in the calls. Yes, to get access to the Dynect API in full, you must enter into a certain relationship with Dyn, and then you will be given the value for this field. We for DinRU , on the basis of Dynect developed a whole happy Internet tools.

As a conclusion. Recently I received a message from one of the well-known Russian Internet companies about the work being done with a request to rewrite the server name in the client’s code to access their resources ... It seems that the architects of this system have never heard of DNS ... Maybe it’s enough to cut the Internet on the knee?

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


All Articles