トップ 履歴 一覧 カテゴリ ソース 検索 ヘルプ RSS ログイン

Source/Perl/DdsnUp-ieServer

INDEX

Dynamic DNS IP更新スクリプト

今は亡き ieServer.Net のダイナミックDNSのIPアドレスの自動更新スクリプトです。

ルータの設定画面から、グローバルIPアドレスを取得して、変わっていた場合に、DDNSの更新要求を行う。動作ログを syslog に記録する。また、変更を行った際に、Twitter のダイレクトメッセージを送る。

対応するルータは、OMRON MR504DV と NTT RV-S340SE、SoftBank E-WMTA2.3 。まぁ、ieServer.Net の回線IP確認ページからも取得できるのですが。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
#!/usr/bin/perl
#####  Character-code is UTF-8. Tab-size is 4 space character.            #####
###############################################################################
## ieServer.Net update Script - Ver.0.00 (2020/01/28)                        ##
###############################################################################
use strict; # restrict unsafe constructs
use warnings; # control optional warnings ( as /usr/bin/perl -w )
use utf8;
use Sys::Syslog qw(openlog syslog closelog LOG_DEBUG LOG_INFO LOG_NOTICE LOG_WARNING LOG_ERR LOG_CRIT LOG_ALERT LOG_EMERG);
use LWP::UserAgent;
use LWP::Protocol::https; # https
use Storable qw(nstore retrieve);

# ieServer.Net アカウント(サブドメイン)情報
my $ACCOUNT  = "account"; # アカウント(サブドメイン)名
my $DOMAIN   = "example.com"; # ドメイン名
my $PASSWORD = "password"; # パスワード

# 設定されてるIPアドレスのローカル保存
my $CURRENT_FILE = __FILE__ . '.dat';
# WEBアクセス時の USER_AGENT
my $USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0';

# DDNS更新ページURL
my $UPDATE_DDNS_URL = "https://ieserver.net/cgi-bin/dip.cgi";
# 回線IP確認ページURL
my $CHECK_IPADD_URL = "https://ieserver.net/ipcheck.shtml";

# OMRON MR504DV の PPPoE 接続状況 / WAN状況 から取得
my $MR504DV_ROUTERIP = undef; #"192.168.65.1";
my $MR504DV_USERNAME = "admin"; # ユーザ名
my $MR504DV_PASSWORD = "pass"; # パスワード
my $MR504DV_PPPOE_URL = $MR504DV_ROUTERIP ? 'http://' . $MR504DV_ROUTERIP . '/disconnect_pppoe.htm' : undef;
my $MR504DV_WAN_URL   = $MR504DV_ROUTERIP ? 'http://' . $MR504DV_ROUTERIP . '/show_wan.htm' : undef;

# NTT RV-S340SE の 現在の状態 から取得
my $RVS340SE_ROUTERIP = undef; #"192.168.65.1";
my $RVS340SE_USERNAME = "user"; # ユーザ名
my $RVS340SE_PASSWORD = "pass"; # パスワード
my $RVS340SE_STATUS_URL = $RVS340SE_ROUTERIP ? 'http://' . $RVS340SE_ROUTERIP . '/cgi-bin/main.cgi?mbg_webname=status' : undef;

#  SoftBank E-WMTA2.3 の 設定情報一覧 から取得
my $SoftBank_ROUTERIP = undef; #"192.168.3.1";
my $SoftBank_USERNAME = "user"; # ユーザ名
my $SoftBank_PASSWORD = "pass"; # パスワード
my $SoftBank_STATUS_URL = $SoftBank_ROUTERIP ? 'http://' . $SoftBank_ROUTERIP . '/settei.html' : undef;


# Twitter OAuth keys [ test client ]
my $CONSUMER_KEY = 'consumer';
my $CONSUMER_SECRET = 'consumer_secret';
# Twitter OAuth keys [ test client - imatake_secret ]
my $ACCESS_TOKEN = 'access_token';
my $ACCESS_SECRET = 'access_secret';
# Twitter ダイレクトメッセージで通知するか
my $SCREEN_NAME = undef; #'your?screen_name';

########################################

openlog(__FILE__, 'pid,perror', Sys::Syslog::LOG_USER); # pid,perror

## 
my $current_ip = &load_current_ip() || '0.0.0.0';
syslog(LOG_DEBUG, 'Current IP addr. ' . $current_ip);
my $remote_ip = &get_remote_ip() || '0.0.0.0';
syslog(LOG_DEBUG, 'Now remote IP addr. ' . $remote_ip);

## 
if( $remote_ip eq '0.0.0.0' ){
  syslog(LOG_WARNING, 'Cannot get remote IP addr.');
}elsif( $current_ip eq $remote_ip ){
  syslog(LOG_DEBUG, 'No dynamic DNS update.');
}else{
  my ($host, $ip) = &update_ddns();
  if( $ip ){
    syslog(LOG_NOTICE, 'Dynamic DNS updated. Remote IP Address=' . $ip . ' HostNama=' . $host);
    &save_current_ip($remote_ip);
    &update_notification($host, $ip) if($SCREEN_NAME);
  }else{
    syslog(LOG_WARNING, 'Cannot dynamic DNS update.');
  }
}

closelog();
exit;

########################################

sub load_current_ip {
    return '0.0.0.0' unless(-f $CURRENT_FILE);
    my $ip = ${retrieve($CURRENT_FILE)};
    return $ip;
}

sub save_current_ip {
    my $ip = shift || return undef;
    nstore(\$ip, $CURRENT_FILE);
    return $ip;
}

########################################

sub update_ddns {
    return undef unless($UPDATE_DDNS_URL);

    my $ua = LWP::UserAgent->new;
    $ua->agent($USER_AGENT);
    $ua->ssl_opts( verify_hostname => 0 ); # ホスト名の検証を無視
    # 
    syslog(LOG_DEBUG , 'Request DDNS update.');
    my $res = $ua->post(
            $UPDATE_DDNS_URL,
            [
                'username' => $ACCOUNT,
                'password' => $PASSWORD,
                'domain' => $DOMAIN,
                'updatehost' => '1',
            ]);
        # submit button name. Update 'updatehost' / Offline 'offline'
    return undef unless($res->is_success);
    syslog(LOG_DEBUG , 'Request DDNS updated.');

    my $html = $res->decoded_content();
    my ($host, $ip) = (undef, undef);
    if( $html =~ /ドメイン名: *([0-9a-zA-Z.]+) *のIPアドレスは現在 *([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+) *に設定されています。/im ){
        $host = $1;
        $ip = $2;
        syslog(LOG_DEBUG , 'DDNS update. host=' . $host . ' ip=' . $ip);
    }
    return wantarray ? ($host, $ip) : $ip;
}

sub get_remote_ip {
    if($MR504DV_ROUTERIP){
        my $ip = undef;
        $ip = &get_remote_ip_from_mr504dv_wan();
        return $ip if($ip);
        $ip = &get_remote_ip_from_mr504dv_pppoe();
        return $ip if($ip);
    }
    if($RVS340SE_ROUTERIP){
        my $ip = undef;
        $ip = &get_remote_ip_from_rvs340se_status();
        return $ip if($ip);
    }
    if($SoftBank_ROUTERIP){
        my $ip = undef;
        $ip = &get_remote_ip_from_SoftBank_status();
        return $ip if($ip);
    }
    ##
    return undef unless($CHECK_IPADD_URL);
    syslog(LOG_DEBUG , 'Check remote IP address.');
    # 
    my $ua = LWP::UserAgent->new;
    $ua->agent($USER_AGENT);
    $ua->ssl_opts( verify_hostname => 0 ); # ホスト名の検証を無視
    my $res = $ua->get($CHECK_IPADD_URL);
    return undef unless($res->is_success);
    return $res->content();
}

########################################

sub get_remote_ip_from_SoftBank_status {
    return undef unless($SoftBank_STATUS_URL);

    my $ua = LWP::UserAgent->new;
    $ua->agent($USER_AGENT);
    my $req = HTTP::Request->new(GET => $SoftBank_STATUS_URL );
    $req->authorization_basic($SoftBank_USERNAME, $SoftBank_PASSWORD);
    my $res = $ua->request($req);
    return undef unless($res->is_success);
    my $html = $res->decoded_content();

    my $ip = undef;
    if( $html =~ /var WANIP="([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)";/i ){
        $ip = $1;
        syslog(LOG_DEBUG , 'Remote IP from SoftBank(status). ip=' . $ip);
    }
    return $ip;
}

sub get_remote_ip_from_rvs340se_status {
    return undef unless($RVS340SE_STATUS_URL);

    my $ua = LWP::UserAgent->new;
    $ua->agent($USER_AGENT);
    my $req = HTTP::Request->new(GET => $RVS340SE_STATUS_URL );
    $req->authorization_basic($RVS340SE_USERNAME, $RVS340SE_PASSWORD);
    my $res = $ua->request($req);
    return undef unless($res->is_success);
    my $html = $res->decoded_content();

    my $ip = undef;
    if( $html =~ /<tr[\s\S]*?<td[\s\S]*?WAN側IPアドレス<\/td[\s\S]*?<td.*?>:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)<\/td[\s\S]*?<\/tr>/i ){
        $ip = $1;
        syslog(LOG_DEBUG , 'Remote IP from RVS340SE(status). ip=' . $ip);
    }
    return $ip;
}

sub get_remote_ip_from_mr504dv_pppoe {
    return undef unless($MR504DV_PPPOE_URL);

    my $ua = LWP::UserAgent->new;
    $ua->agent($USER_AGENT);
    my $req = HTTP::Request->new(GET => $MR504DV_PPPOE_URL );
    $req->authorization_basic($MR504DV_USERNAME, $MR504DV_PASSWORD);
    my $res = $ua->request($req);
    return undef unless($res->is_success);
    my $html = $res->decoded_content();

    my $ip = undef;
    if( $html =~ /<TR.*><TD.*>割り当てIPアドレス.*<\/TD><TD.*>([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)<\/TD><\/TR>/i ){
        $ip = $1;
        syslog(LOG_DEBUG , 'Remote IP from MR504DV(PPPoE). ip=' . $ip);
    }
    return $ip;
}

sub get_remote_ip_from_mr504dv_wan {
    return undef unless($MR504DV_WAN_URL);

    my $ua = LWP::UserAgent->new;
    $ua->agent($USER_AGENT);
    my $req = HTTP::Request->new(GET => $MR504DV_WAN_URL );
    $req->authorization_basic($MR504DV_USERNAME, $MR504DV_PASSWORD);
    my $res = $ua->request($req);
    return undef unless($res->is_success);
    my $html = $res->decoded_content();

    my $ip = undef;
    if( $html =~ /<TR.*><TD.*>IPアドレス.*<\/TD><TD.*>([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)<\/TD><\/TR>/i ){
        $ip = $1;
        syslog(LOG_DEBUG , 'Remote IP from MR504DV(WAN). ip=' . $ip);
    }
    return $ip ne '0.0.0.0' ? $ip : undef;
}

sub update_notification {
    my $host = shift;
    my $ip   = shift;
    eval { use Net::Twitter; };
    #
    my $twit = Net::Twitter->new(traits => ['API::RESTv1_1', 'OAuth'], ssl => 1,
        consumer_key => $CONSUMER_KEY, consumer_secret => $CONSUMER_SECRET, );
    $twit->access_token($ACCESS_TOKEN);
    $twit->access_token_secret($ACCESS_SECRET);
    #
    $host =~ s/\./ . /g;
    my $status = 'Update Dynamic DNS (ieServer . Net). Remote IP Address=' . $ip . ' HostNama=' . $host;
    $twit->new_direct_message({ screen_name => $SCREEN_NAME, text => $status });
}

###############################################################################
##    End Of File (ddns-update.pl)                                           ##
###############################################################################

最終更新時間:2022年01月25日 23時40分22秒 指摘や意見などあればSandBoxのBBSへ。

ddns-update.pl