Aria

Klasa (Java) zmieniająca automatycznie nr IP w DynHost (OVH)

Mamy do rozwiązania następujące problemy:

Musimy napisać program, który:

  • wykrywa zmianę IP serwera
  • informuje OVH o zmianie IP
  • automatycznie ‘przeciska się’ przez okienko logowania OVH
Klasa
package mydynserv;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;

public class MyDynServ1 {
    public static void main(String[] args) {
        //-
        String localhost = null;
        try {
            localhost = Inet4Address.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            Logger.getLogger(MyDynServ1.class.getName()).log(Level.ALL, e.getLocalizedMessage());

        }
        System.out.println("Local IP Address: " + localhost);
        String oldip = null;
        try {
            oldip = Inet4Address.getByName("ematma.com").getHostAddress();
        } catch (UnknownHostException e) {
            Logger.getLogger(MyDynServ1.class.getName()).log(Level.ALL, e.getLocalizedMessage());
        }
        System.out.println("Public IP Address (old): " + oldip);
        String newip = null;
        try {
            URL url =  new URL("https://api6.ipify.org/?format=text&callback=getIP");
            BufferedReader sc =
                    new BufferedReader(new InputStreamReader(url.openStream()));
            newip = sc.readLine().trim();
        } catch (Exception e) {
            Logger.getLogger(MyDynServ1.class.getName()).log(Level.ALL, e.getLocalizedMessage());
        }
        System.out.println("Public IP Address (new): " + newip);
        if (!oldip.equals(newip)) {
            URL url2 = null;
            HttpURLConnection huc = null;
            String userName = "ematma.com-aria";
            char[] chars = "password".toCharArray();
            try {
                url2 = new URL("https://www.ovh.com/nic/update?system=dyndns&hostname=ematma.com&myip=" + newip);
                huc = (HttpURLConnection) url2.openConnection();
                huc.setAuthenticator(new Authenticator() {
                    @Override
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(userName, chars);
                    }
                });
                System.out.println(huc.getResponseCode());
                System.out.println(huc.getResponseMessage());
            } catch (IOException e) {
                Logger.getLogger(MyDynServ1.class.getName()).log(Level.ALL, e.getLocalizedMessage());
            }
        }
    }
}

Otrzymujesz informację o starym i nowym (zmienionym) nr IP. Nowy nr IP jest automatycznie wpisywany w rekordzie
DynHost.

Jeżeli ‘old’ i ‘new’ są jednakowe – numer serwera (rutera) się nie zmienił i nie ma potrzeby zmiany w OVH.

Jeżeli klasa zostanie uruchomiona dwa razy w zbyt krótkim okresie (wyznaczanym przez OVH) numer ‘old’ może być
powtórzony na konsoli (tak jakby się nie zmienił), mimo że w OVH został już zmieniony. To nie jest wada klasy
lecz blokada przez sesje serwera.

W końcowym pliku warto usunąć wszystkie nieistotne informacje (lokalny IP) i wszystkie użycia System.out.println.

A oto nasza klasa w wersji minimalnej:

package mydynserv;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;

public class MyDynServ2 {
    public static void main(String[] args) {
        String oldip = null;
        try {
            oldip = Inet4Address.getByName("ematma.com").getHostAddress();
        } catch (UnknownHostException e) {
            Logger.getLogger(MyDynServ2.class.getName()).log(Level.ALL, e.getLocalizedMessage());
        }
        String newip = null;
        try {
            URL url =  new URL("https://api6.ipify.org/?format=text&callback=getIP");
            BufferedReader sc =
                    new BufferedReader(new InputStreamReader(url.openStream()));
            newip = sc.readLine().trim();
        } catch (Exception e) {
            Logger.getLogger(MyDynServ2.class.getName()).log(Level.ALL, e.getLocalizedMessage());
        }
        if (!oldip.equals(newip)) {
            URL url2 = null;
            HttpURLConnection huc = null;
            String userName = "ematma.com-aria";
            char[] chars = ("password").toCharArray();
            try {
                url2 = new URL("https://www.ovh.com/nic/update?system=dyndns&hostname=ematma.com&myip=" + newip);
                huc = (HttpURLConnection) url2.openConnection();
                huc.setAuthenticator(new Authenticator() {
                    @Override
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(userName, chars);
                    }
                });
                huc.getResponseCode();
                huc.getResponseMessage();
            } catch (IOException e) {
                Logger.getLogger(MyDynServ2.class.getName()).log(Level.ALL, e.getLocalizedMessage());
            }
        }
    }
}

Automatyzacja

Gdy program jest gotowy (klasa działa tak jak powinna) należy

— zapewnić automatyczne, cykliczne uruchamianie powyższego programu

Program można uruchamiać, najlepiej w skrypcie .bat uruchamianym przez harmonogram Windows 7.

Można by też uruchamiać z poziomu Autostartu albo można utworzyć plik .exe odpalany z harmonogramu albo odpalany jako usługa Windows.

Ten program nie musi być stale uruchomiony, a tylko powinien być odpalany od czasu do czasu. W ten sposób można zaoszczędzić pamięć. Ja u siebie uruchamiam plik .java (bez kompilacji) z pliku .bat, uruchamianego co 5 min. przez harmonogram Windows.

Uzupełnienie / Poprawka

W praktyce okazało się, że powyższa klasa nie jest do końca poprawna. Błędnie założyłam, że nr IP ma stała długość, a przecież każdy z 4 segmentów może się składać z od 1 do 3 cyfr.

Dlatego klasę należy poprawić jak poniżej:

 String oldip = null;
        try {
            oldip = Inet4Address.getByName("ematma.com").getHostAddress();
        } catch (UnknownHostException e) {
            Logger.getLogger(MyDynServ2.class.getName()).log(Level.ALL, e.getLocalizedMessage());
        }        
        String newip = null;
        try {
            URL url = new URL("https://api64.ipify.org/?format=json&callback=getIP");
            BufferedReader sc =
                    new BufferedReader(new InputStreamReader(url.openStream()));
            newip = sc.readLine().trim();
            int pos = newip.indexOf("}");
            newip = newip.substring(7,pos-1);
            System.out.println(newip);
        } catch (Exception e) {
            Logger.getLogger(MyDynServ2.class.getName()).log(Level.ALL, e.getLocalizedMessage());
        }