Home » Program » sendmail 送信元 IP アドレス自動切替え (Part 2) (Tag: , )

sendmail 送信元 IP アドレス自動切替え (Part 1) の続きです。

プログラム概要は以下の通りです。

  • 現在の送信元 IP アドレスと IP アドレスプールを取得。
  • ブラックリストデータベース別に IP アドレスプールすべての A レコード登録の検索。(今回は SpamCop のみ) –> 利用可能な IP アドレスの収集。
  • A レコードが返る場合 (検索対象の IP アドレスが 202.152.209.33 とし、33.209.152.202.bl.spamcom.net の A レコードが 127.0.0.2 と検索された場合) は “Info: MX Address Down” で通知。
  • 返らない場合は “Info: MX Address Up” で通知。
  • 利用可能な IP アドレスが 0 の場合は “MX Address: ” で警告通知。
  • 現在の送信元 IP アドレスが A レコードが存在する場合、利用可能な IP アドレスの先頭を新送信先とする。

SpamCop 以外のブラックリストデータベースにも対応する場合は、check_spamcop() を流用し、77 行目の前後に追加すれば良いでしょう。

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
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
#!/usr/bin/perl -w
#
# blcheck.pl
#
 
#// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#// use Module
#// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
use strict;
 
use Net::DNS;
use Net::IP;
 
#// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#// Controller
#// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
    #// ----------------------------------------------------------
    #// Option Parse
    #// ----------------------------------------------------------
 
    my @basename = split(/\//, $0);
    my $basename = pop(@basename);
 
    #// ----------------------------------------------------------
    #// Item Set
    #// ----------------------------------------------------------
 
    my $item = {
        mkdir    => '/bin/mkdir',
        cat      => '/bin/cat',
        chmod    => '/bin/chmod',
        ps       => '/bin/ps',
        hostname => '/bin/hostname',
        mail     => '/usr/bin/mail',
        awk      => '/usr/bin/awk',
        grep     => '/usr/bin/grep',
        chown    => '/usr/sbin/chown',
 
        sed      => '/usr/bin/sed',
        ifconfig => '/sbin/ifconfig',
        sendmail => '/usr/local/etc/rc.d/sendmail.sh',
        cf       => '/etc/mail/sendmail.cf',
 
        dir      => '/home/tools/blcheck/',
        maddr    => 'trouble@example.jp',
 
        base     => $basename,
        file     => '/tmp/.' . $basename
    };
 
    if ( !-d $item->{dir} ) {
        `$item->{mkdir} $item->{dir}`;
        `$item->{chmod} 750 $item->{dir}`;
    }
 
    my $host = `$item->{hostname}`; chomp $host;
    $item->{host} = $host;
 
    #// bl define
 
    $item->{spamcop} = {
        target => '.bl.spamcop.net',
        result => '127.0.0.2',
    };
 
    my $ipaddr = {};
 
    #// ----------------------------------------------------------
    #// Start
    #// ----------------------------------------------------------
 
    #// List
 
    $ipaddr = check_ipaddr($item, $ipaddr);   #// src, alias
    $ipaddr = check_spamcop($item, $ipaddr);
 
    #// Change
 
    my $old = $ipaddr->{src};
    my $new = {};
    my @new = ();
 
    foreach (@{$ipaddr->{alias}}) {
        next if ($ipaddr->{blist}->{$_});
 
        $new->{$_} = 1;
        push(@new, $_);
    }
 
    my $src = $ipaddr->{src};
 
    if ($new->{$src}) {
 
    } else {
        if (@new == 0) {
            report_ipna($item, $old);
 
        } else {
            chg_cf($item, $old, $new[0]);
            report_chg($item, $old, $new[0]);
        }
    }
 
#// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#// Model
#// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
sub utime2date {
    my ($sec, $min, $hours, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($_[0]);
 
    my $years    = $year + 1900;
    my $this_mon = sprintf("%02d",$mon + 1);
 
    $mday  = sprintf("%02d", "$mday");
    $hours = sprintf("%02d", "$hours");
    $min   = sprintf("%02d", "$min");
    $sec   = sprintf("%02d", "$sec");
 
    my $date = "$years/$this_mon/$mday $hours:$min:$sec";
 
    return $date;
}
 
sub check_ipaddr {
    my ($item) = @_;
 
    my $ipaddr = {};
 
    #// check source ipaddr
 
    my $line = `$item->{cat} $item->{cf} | $item->{grep} "^O ClientPortOptions"`;
 
    $line =~ s/Address=(.*)/$1/;
    $ipaddr->{src} = $1;
 
    #// check stock ipaddr
 
    my @list0 = `$item->{ifconfig} | $item->{grep} "0xffffffff" | $item->{awk} '{print \$2}'`;
 
    my @list = ();
 
    foreach (@list0) {
        chomp;
 
        my $ref = new Net::IP("$_");
        next unless ($ref->iptype() =~ /public/i);
 
        push(@list, $_);
    }
 
    $ipaddr->{alias} = \@list;
 
    return $ipaddr;
}
 
sub check_spamcop {
    my ($item, $ipaddr) = @_;
 
    foreach (@{$ipaddr->{alias}}) {
        my @rev   = reverse(split(/\./, $_)); $" = '.';
        my $line  = "@rev" . $item->{spamcop}->{target};
        my $check = check_rr($line, $item->{spamcop}->{result});
 
        if ($check) {
            $ipaddr->{blist}->{$_} = $check;
 
            report_down($item, $_, 'spamcop', tml_spamcop($_));
 
        } else {
            my $file = file_down($item, $_, 'spamcop');
 
            if ( -e $file ) {
                report_up($item, $_, 'spamcop', $file);
 
                unlink($file);
            }
        }
    }
 
    return $ipaddr;
}
 
sub tml_spamcop {
    my ($ip) = @_;
 
    my $tml = <<"TML";
#// SpamCop (http://www.spamcop.net/)
 
http://www.spamcop.net/w3m?action=checkblock&ip=$ip
 
http://www.spamcop.net/w3m?action=dispute;ip=$ip
 
TML
 
    return $tml;
}
 
sub check_rr {
    my ($line, $result) = @_;
 
    my $res   = Net::DNS::Resolver->new;
    my $query = $res->search($line);
    my $check = 0;
 
    if ($query) {
        foreach my $rr ($query->answer) {
            next unless ($rr->type eq "A");
 
            if ($rr->address eq $result) {
                $check = 1;
                last;
            }
        }
    }
 
    return $check;
}
 
sub chg_cf {
    my ($item, $old, $new) = @_;
 
    `$item->{sed} -i'.0' -e 's/Address=$old/Address=$new/' $item->{cf}`;
    `$item->{sendmail} restart`;
 
    sleep(5);
}
 
#// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#// Model (Report)
#// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
sub file_down {
    my ($item, $ip, $btype) = @_;
 
    my $file = $item->{dir} . $ip . '.' . $btype;
 
    return $file;
}
 
sub report_down {
    my ($item, $ip, $btype, $tml) = @_;
 
    my $time = utime2date(time());
    my $down = file_down($item, $ip, $btype);
 
    open WRITE, "+>$down";
    print WRITE $time;
    close WRITE;
 
    my $file = $item->{file};
    my $subj = "Info: MX Address Down ($item->{host})";
 
    my $body = <<"BODY";
$time => $ip (add $btype)
 
$tml
BODY
 
    report($item, $file, $subj, $body);
}
 
sub report_up {
    my ($item, $ip, $btype, $down) = @_;
 
    my $time  = utime2date(time());
    my $time0 = `$item->{cat} $down`; chomp $time0;
 
    my $file = $item->{file};
    my $subj = "Info: MX Address Up ($item->{host})";
 
    my $body = <<"BODY";
$time0 -> $time => $ip (del $btype)
BODY
 
    report($item, $file, $subj, $body);
}
 
sub report_chg {
    my ($item, $old, $new) = @_;
 
    my $time = utime2date(time());
 
    my $file = $item->{file};
    my $subj = "Info: MX Address Change ($item->{host})";
 
    my $body = <<"BODY";
$time => $old -> $new (restart)
BODY
 
    report($item, $file, $subj, $body);
}
 
sub report_ipna {
    my ($item, $old) = @_;
 
    my $time = utime2date(time());
 
    my $file = $item->{file};
    my $subj = "MX Address ($item->{host})";
 
    my $body = <<"BODY";
$time => $old -> Failed: No IP Address Pool
BODY
 
    report($item, $file, $subj, $body);
}
 
sub report {
    my ($item, $file, $subj, $body) = @_;
 
    open  FILE, "+>$file";
    print FILE $body;
    close FILE;
 
    `$item->{mail} -s "$subj" $item->{maddr} < $file`;
 
    unlink($file);
}

Random Select

パーラー島風 (6)
銀座わしたショップ 2014/06/13 (コンビーフハッシュ) の続きです。銀座わしたショップ 2013/07/05 (パーラー島風 ソフトクリーム) 以来ほぼ 1 年ぶりに訪れましたが、雰囲気が少
こなゆきコラーゲン BODY SAVON (4)
タマチャンショップ には こなゆきコラーゲン や YASAI シャンプー & ヘアパック でお世話になっていますが、こなゆきコラーゲン BODY SAVON も 2 個目のリピートとなりました
ANA ポケモンジェット (2013/05/19)
2013/09/30 にすでにラストフライトを終えた ANA の ポケモンジェット に、過去 2 回乗り合わせたことがあります。2012/05/27 の沖縄出張への往路です。ピカチュウジャンボ (JA
ボンディ 通信販売 ビーフカレー (5)
自宅 de ボンディ (Part 2) の続きです。2 回目1 回目は土曜日のランチ、2 回目は翌日日曜日のランチです。"お酒は我慢出来てもカレーは難しい" 私にとって、2 日連続
ワイルドハンバーグ 300g (1)
いきなり ! ステーキ (ワイルドステーキ 300g) でデビューした いきなり ! ステーキ で、今度はランチメニューのワイルドハンバーグを試すべく再び小川町店を訪れましたが、まだ 13 時過ぎで何
Facebook, WordPress Logo
Facebook 向けに OGP (Open Graph Protocol) に対応する方が望ましいとした場合、やはり Valid にはなりません。HTML5 + RDFa ? 等も考えられますが、発
VAIO Fit 13A (背面)
Windows 8.1 でステータスバーに詳細表示する OldNewExplorer で "Windows 8.1 であれば Classic Shell を入れる程不便は感じていない&qu
ロコモコ (テリヤキソース, 大盛り)
以前、銀座にサテライトオフィスを設けてそちらに勤務していたことがありました。日本一美味しいサバの塩焼き串八珍 (かつ丼)その時に開拓した Pour~cafe’ (プルーカフェ) に久しぶりに足を延ばし
WS-C2960S-48TS-L (1)
Cisco Catalyst 2960S IOS Update (Part 2) の続きです。今回は 15.0 系からのアップデートですが、12.2 系とはやや出力が異なりました。アップデート 15.
辛つけ麺 (中) + 半熟玉子
三田製麺所 (つけ麺) で開店間もない御茶ノ水店を訪れて 1 週間も空けずに再び訪れました。辛つけ麺が気になっていたからです。つけ麺さとう (辛つけ麺)つけ麺屋やすべえ (辛味つけ麺)近場にすでにある
Valid HTML5 Valid CSS3 Another HTML Lint