いますぐ実践! Linuxシステム管理

いますぐ実践! Linux システム管理 / Vol.256 / 読者数:2563名

たいへんご無沙汰いたしております、うすだです。

3月は本当に余裕がなく、3月分の2回をまるっと休んでしまいました。
たいへん申し訳ありません。

ちなみに、2月末に9周年を迎えていたはずなのですが、 それも過ぎ去ってしまいました。10周年は盛大に祝おうと思います。 個人的に。地味に。

まあしかし、余裕がなかったと言いつつも、 メルマガを書けないほど過密だったわけではなく、 ちょっとずつ考えたり書いたりすれば、すっぽかすこともなかったはずです。

たとえば、昔、仕事先で軟禁されていたとき、朝の4時にホテルについてから、 当メルマガをなんとか発行したことがあります。

そのころはまだ30代で元気だった…からかもしれませんが、それだけではなく、 絶対発行するんだ! という気迫というか、覚悟というか、使命感というか、 うまくヒトコトで言い表しにくいのですが、一線を越えてはダメだ! 的な何かが、 確実に存在しました。

それが徐々に失われつつあるのは、 過去に何度かすっぽかしたという負の実績があるから、というのもありますが、 当メルマガの本来の目的や目標を見失いつつあるから、 という理由が大きなウェイトを占めているように思っています。

何のために発行するのか、誰に何を伝えたいのか、もう一度よく考えて、 その上で続けていきたいと思います。

…特にオチはありませんが、今回もはりきってまいります。

今回のお題 - サブネット内のマシンをてっとり早く知る (レベル:初級)

前回…遠い遠い昔のことのように思われますが…は、 arpwatch を使ってMACアドレスとIPアドレスの対をかき集める、というネタでした。

Vol.255 - arpwatch でMACアドレスをかき集める
http://www.usupi.org/sysad/255.html

ただ、飛び交うARPパケットをかき集めるという行為は、受動的であり、 長期にわたってじっくりできる場合に限られるのではないかと思います。

やや不正確でもよく、そのとき稼働していないマシンはピックアップできなくてもよい、 とにかく今すぐ知りたいという場合、arpwatch はあまり適していません。

じゃあ他の方法が何かあるだろうか、というわけで、今回は、能動的に、 てっとり早くかき集める方法を考えてみたいと思います。

ARP(Address Resolution Protocol) のおさらいと arp コマンド

前回と説明が繰り返しになってしまいますが、おさらいの意味も含めて、 ARP について簡単に説明します。

ARP とは、IPアドレスから MAC アドレスを得るためのプロトコルです。

TCP/IP では、同じサブネット内のマシンとは、 (Ethernetなどを介して)直接通信します。そのとき、 IPパケットを相手に送信するために、 下位層のEthernetで使われるMACアドレスを知る必要があります。

そのため、このIPアドレスを使っているマシンの MAC アドレスを教えてくれ、 という ARP リクエストパケットをブロードキャストします。
すると相手が、MAC アドレスはこれですという ARP リプライパケットを返します。

で、なにか通信を行う度に、上記のような ARP のやりとりをしていたのでは、 効率が悪すぎます。そのため、カーネルの中にテーブルを用意し、 そこに一定期間保持するようにしています。これを ARP テーブルと呼びます。

ARPテーブルに情報があれば、ARPのやりとりを行わず、 その情報を使って通信を行います。

 

ARP テーブルの中を確認したり、手動でエントリを追加・削除したりするコマンドが、 「arp」です。

「-a」オプションを指定して実行すると、一覧が表示されます。

  $ arp -a
  homegw (192.168.1.1) at 00:01:02:03:04:05 [ether] on eth0
  www (192.168.1.2) at 00:02:04:06:08:0a [ether] on eth0
  ...後略...

「-n」オプションをつけると、いちいちホスト名を確認せず、 IPアドレスだけを出力します。名前解決に時間がかかるときに重宝します。

  $ arp -an
  ? (192.168.1.1) at 00:01:02:03:04:05 [ether] on eth0
  ? (192.168.1.2) at 00:02:04:06:08:0a [ether] on eth0
  ...後略...

エントリを削除するには、 「-d」オプションとIPアドレス(かホスト名)を指定して実行します。 マシンが変わったのに、まだ ARP テーブルに古い情報が残っているといった場合に、 使います。

  # arp -d 192.168.1.1       (root権限で実行する場合)
  $ sudo arp -d 192.168.1.1  (一般ユーザで実行する場合)

あ、ちなみに、追加や削除には、root の権限が必要です。
以降では、root権限が必要な操作のプロンプトに、「#」を用います。
# が付いている場合は、root になって実行するか、 あるいは上記のように sudo コマンド経由で実行してください。

さて、「-s」オプションとIPアドレス、MACアドレスを指定して実行すると、 エントリを追加することができます。

  # arp -s 192.168.1.11 0:f:e:d:c:b
  $ arp -an
  ...中略...
  ? (192.168.1.11) at 00:0f:0e:0d:0c:0b [ether] PERM on eth0

手動で追加した場合、一定期間経過後に消されることなく、 ARP テーブルにずっと残るため、「PERM」という印がつきます。
ずっと残したくない場合は、最後の引数に「temp」を指定します。

  # arp -s 192.168.1.12 0:e:c:a:8:6 temp
  $ arp -an
  ...中略...
  ? (192.168.1.12) at 00:0e:0c:0a:08:06 [ether] on eth0

ping で情報をかき集める

さて、ようやく本題に入ります。

いま知りたいのは、稼働しているマシンです。
とりあえず思いつくのは、手当たり次第に ping を撃ちまくることです。

  $ ping 192.168.1.128
  PING 192.168.1.128 (192.168.1.128) 56(84) bytes of data.
  64 bytes from 192.168.1.128: icmp_seq=1 ttl=64 time=0.082 ms
  64 bytes from 192.168.1.128: icmp_seq=2 ttl=64 time=0.076 ms
  64 bytes from 192.168.1.128: icmp_seq=3 ttl=64 time=0.084 ms

  ([Ctrl]+[C] を押して中断しましょう)

  --- 192.168.1.128 ping statistics ---
  3 packets transmitted, 3 received, 0% packet loss, time 1998ms
  rtt min/avg/max/mdev = 0.076/0.080/0.084/0.010 ms

とはいえ、たとえば、対象のサブネットが 192.168.1.0/24 だとしたら、 192.168.1.1 から 192.168.1.254 までの254個に対して、 上記を実行する必要があります。これを手動でやるのは…途方に暮れますね。

幸い、ping コマンドには「-c」オプションで回数を指定できます。
そして、返事がある場合、終了ステータスは 0 です。

  $ ping -c 1 192.168.1.128
  PING 192.168.1.128 (192.168.1.128) 56(84) bytes of data.
  64 bytes from 192.168.1.128: icmp_seq=1 ttl=64 time=0.080 ms

  --- 192.168.1.128 ping statistics ---
  1 packets transmitted, 1 received, 0% packet loss, time 0ms
  rtt min/avg/max/mdev = 0.080/0.080/0.080/0.000 ms
  $ echo $?
  0

返事がなければ、終了ステータスが 0 になりません。

  $ ping -c 1 192.168.1.129
  PING 192.168.1.129 (192.168.1.129) 56(84) bytes of data.
  From 192.168.1.128 icmp_seq=1 Destination Host Unreachable

  --- 192.168.1.129 ping statistics ---
  1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
  $ echo $?
  1

返事がない場合、数秒待たされますが、「-W」オプションと秒数を引数に指定して、 タイムアウトを短くすることができます。

  $ ping -c 1 -W 1 192.168.1.129
  ...後略...

ただ、ping に答えない(ICMP Echo Reply パケットを返さない) マシンが世の中には少なからず存在します。 ping の終了ステータスが0でないからといって、 稼働していないと判断することはできません。

ですが、ARP リクエストまでも無視するマシンは、特別な理由がない限りは、 ほぼないと言っていいです。ですので、 ping 実行後に ARP テーブルを確認すればよさそうです。

  $ ping -c 1 -W 1 192.168.1.129
  ...中略...
  $ arp -an 192.168.1.129
  ? (192.168.1.129) at 00:01:02:04:08:10 [ether] on eth0
  $ ping -c 1 -W 1 192.168.1.130
  ...中略...
  $ arp -an 192.168.1.130
  ? (192.168.1.130) at <incomplete> on eth0

…はい、よさそうですね。
というわけで、192.168.1.1〜192.168.1.254 のIPアドレスと MACアドレスの対を確認するスクリプトを書いてみました。

#!/bin/sh
for n in $(seq 1 254); do
    IPADDR="192.168.1.$n"
    ping -W 1 -c 1 $IPADDR > /dev/null
    LANG=C arp -an $IPADDR | awk "{ print \"$IPADDR\", \$4 }"
done

これを、たとえば searchhost.sh というファイル名で保存したら、実行権をつけて、 実行してみます。

  $ chmod +x searchhost.sh
  $ ./searchhost.sh
  192.168.1.1 <incomplete>
  192.168.1.2 <incomplete>
  192.168.1.3 00:01:00:02:00:03
  ...後略...

稼働していないマシンは「<incomplete>」と表示されます。 それが余計だと思われるなら、下記のように grep を使ってください。

  $ ./searchhost.sh | grep -v incomplete
  192.168.1.3 00:01:00:02:00:03
  ...後略...

というわけで、とりあえず情報を収集できるようになりました。

もうちょっと早くかき集める

とはいえ、1つのマシンの確認に1秒程度かかっていますので、 上記を実行し終わるまで4分少々かかります。

  $ date; ./searchhost.sh | grep -v incomplete; date
  2014年  4月  6日 日曜日 15:17:37 JST
  192.168.1.3 00:01:00:02:00:03
  ...中略...
  2014年  4月  6日 日曜日 15:21:49 JST

クラスCだからまだよいですが、これがクラスBやクラスAになりますと、 それぞれ 65534秒≒18時間, 16777214秒≒194日 もかかってしまいます。

別に ping に限らず、なんらかの通信をしてくれさえすれば、 ARP によるMACアドレスの取得と ARP テーブルへの登録を行ってくれるはずです。

というわけで、1秒未満のタイムアウトを指定できる、 なにか通信を行うコマンドがないか探してみたところ、「traceroute」がありました。

「-w」オプションで指定するタイムアウトの秒数は、小数でも可能です。
ただ、下記のように、TTLを延ばしてトライし続けます。

  $ traceroute -w 0.5 192.168.1.1
  traceroute to 192.168.1.1 (192.168.1.1), 30 hops max, 60 byte packets
   1  * * *
   2  * * *
   3  * * *
   4  * * *
   5  * * *
   6  * * *
  ...後略...

ですので、「-m」オプションと最大TTLを指定して実行します。

  $ traceroute -m 1 -w 0.5 192.168.1.1
  traceroute to 192.168.1.1 (192.168.1.1), 30 hops max, 60 byte packets
   1  * * *
  $ 

あ、これで、なんだかいけそうですね。というわけで、スクリプトです。

#!/bin/sh
for n in $(seq 1 254); do
    IPADDR="192.168.1.$n"
    traceroute -w 0.5 -m 1 $IPADDR > /dev/null
    LANG=C arp -an $IPADDR | awk "{ print \"$IPADDR\", \$4 }"
done

これを、searchhost2.sh というファイル名で保存したとすると、 先ほどと同様に実行してみます。

  $ chmod +x searchhost2.sh
  $ date; ./searchhost2.sh | grep -v incomplete; date
  2014年  4月  6日 日曜日 15:10:09 JST
  ...中略...
  2014年  4月  6日 日曜日 15:12:21 JST

2分少々と、先ほどの半分程度に短縮できました。
ちなみに、こちらの環境では、タイムアウトに 0.2 を指定しても、 問題なく動作しました。0.1 だとちょっと厳しいようです。

おわりに

以上、MACアドレスとIPアドレスの対を能動的にかき集める方法を、簡単に紹介しました。

自力で ARP リクエストを送信するものでも作れば、 もっと効率よく動作させられそうですが、 アリモノで簡単にできた方がよいだろうと思って、その方法を少し模索してみました。

もっといい方法があるなど、ご存じでしたら、ぜひご教示くださいませ。

宿題の答え

前回の宿題は、

  arp.dat の内容をDBに登録(更新)するようにしてみましょう。

でした。

…そもそも何の話でしたっけ、と聞かれても仕方がないのですが、 これは arpwatch の話です。

arpwatch は、/var/lib/arpwatch/arp.dat (あるいは I/F名.dat) というファイルに対して、15分おきに、1行に1つ、 下記のフォーマットの情報を出力します。

  MACアドレス  IPアドレス  日時  ホスト名  I/F名

じゃあ、arp.dat を読み込んで DB に登録するモノを作り、 定期的に実行するよう仕込めばよさそうですね。

以降では、MySQLに登録(更新)することを目指したいと思います。
まず、あらかじめ「arpwatch」というテーブルを作っておきます。
(さりげなく、パスワードなしで使えるようにしています。その辺りは、 お察しいただけますと幸いです。)

  $ mysql -h ホスト名 -u ユーザ名
  mysql> use データベース名;
  mysql> create table arpwatch (macaddr VARCHAR(17) unique,
      -> ipaddr VARCHAR(15), time DATETIME);
  mysql> quit

次に、以下のスクリプトを用意します。
以下をテキストエディタにコピペするなどしてください。

#!/bin/sh
while read macaddr ipaddr sec host iface; do
    timestamp=$(date --date="@$sec" +"%F %T")
    mysql -h ホスト名 -u ユーザ名 << E-O-F
use データベース名;
insert into arpwatch ( macaddr, ipaddr, time ) values (
  "$macaddr", "$ipaddr", "$timestamp" )
  on duplicate key update macaddr = "$macaddr";
E-O-F
done < /var/lib/arpwatch/arp.dat

これを、たとえば「/home/usu/bin/arpwatch2mysql.sh」 というファイル名で保存したら、試しに実行してみます。 一般庶民の権限では /var/lib/arpwatch/arp.dat を読むことができないので、 arpwatch ユーザの権限で実行します。

  $ sudo -u arpwatch ~/bin/arpwatch2mysql.sh

実際に登録されたかどうか確認します。

  $ mysql -h ホスト名 -u ユーザ名
  mysql> use データベース名;
  mysql> select * from arpwatch;
  +-------------------+---------------+---------------------+
  | macaddr           | ipaddr        | time                |
  +-------------------+---------------+---------------------+
  | 00:01:02:03:04:05 | 192.168.1.129 | 2014-04-01 23:57:27 |
  | 00:02:04:06:08:0a | 192.168.1.130 | 2014-04-02 00:11:41 |
  | 00:03:06:09:0c:0f | 192.168.1.131 | 2014-04-02 01:22:11 |
  ...後略...

登録されていますね。
ちなみに、同じMACアドレスのレコードがある場合は、その情報を上書きします。 実行する度に増えていく、という心配は不要です。

あとは、15分おきに実行されるよう、cron で設定するだけです。
こちらは、たとえば太古の昔に書いた以下などを参考にしてください。

Vol.002 - 簡易バックアップ リローデッド
http://www.usupi.org/sysad/002.html

今回の宿題

今回の宿題は、

  クラスBのサブネットで稼働中のマシンを知るためのシェルスクリプト
  を作ってみましょう。

です。

…いや、まあ、for文の2重ループにするだけですが…。

あとがき

というわけで、記念すべき256号を、なんとか発行できました。
読者数も、減ることなく、それっぽい人数になっていて、感謝感激です。

ちなみに、まぐまぐでは、創刊2年以上で、かつ読者数が3千人以上になると、 「殿堂入り」メルマガと認定されます。

今、2560名程度ですので、あと440名。1日1名増えるとしたら、 1年少々で殿堂入りしそうです。

そのペースで読者を増やし続けられるのか、 そもそもメルマガをそれまで存続できるのかなど、不安要素はたくさんありますが、 まずは殿堂入りを目指して、がんばってみようと思います。

…あ、目的とか目標とか、配信形態も考えつつ…です…はい…。

 

今回も、ここまで読んでいただき、誠にありがとうございました。
次回は、4月20日(日) の未明にお会いしましょう!

 

「いますぐ実践! Linux システム管理」の解除は、以下からできます。
http://www.usupi.org/sysad/ (まぐまぐ ID:149633)

バックナンバーは、こちらにほぼ全部そろっています。
http://www.usupi.org/sysad/backno.html

「栗日記」- 忙しいときは出来がビミョーです。
http://www.usupi.org/kuri/ (まぐまぐ ID:126454)
http://usupi.seesaa.net/ (栗日記ブログ)
http://usupi.org/k/ (モバイル栗日記)
http://twitter.com/kuriking/ (栗つぶやき)
http://facebook.com/kuriking3 (栗顔本)


[バックナンバーのトップへ] [Linux システム管理のトップへ]

トップ

バックナンバー
    [日付順] [目的別]

プロフィール

▼ リンク

独学Linux
Linuxデスクトップ環境に関する情報が満載です。 メルマガもありますよ。
Server World
CentOS 6をサーバとしたときの設定例が、これでもかというくらいたくさん載っています。 CentOS以外のディストリビューション(Fedora, Ubuntu)も充実しています。
LINUXで自宅サーバーを構築・導入(Fedora9)
Fedora9のインストールの仕方から管理方法まで、詳しく載っています。 SearchManには情報がもりだくさんです。
マロンくん.NET
〜サーバ管理者への道〜
Linuxをサーバとして使用するための、いろいろな設定方法が載っています。 マロンくんもかわいいです。 なんといっても、マロンくんという名前がいいですね!!
日経Linux
今や数少なくなってしまったLinuxの雑誌。ニュースやガイドもあります。
Linux Square − @IT
@ITが提供する、Linux の情報が満載。 載っていない設定方法はないんじゃないでしょうか。
gihyo.jp…技術評論社
Linuxに限らず様々な技術情報が満載のサイト。 SoftwareDesign誌も、 ソフトウェア技術者は必見です。
SourceForge.JP Magazine
Linux に限らず、オープンソース関連の記事が網羅されています。
ITmediaエンタープライズ:Linux Tips 一覧
Tips というより FAQ 集でしょうか。わからないことがあれば覗きましょう。
IBM developerWorks : Linux
開発者向けですが、勉強になりますよ。
Yahoo!ニュース - Linux
Yahoo!のLinuxに関するニュース一覧です。
栗日記
システム管理とかと全然関係ありませんが、毎日栗の絵を描いています。
システム管理につかれちゃったとき、癒されたいときに、ご覧ください。:-)
WEB RANKING - PC関連
ランキングに参加してみました。押してやってください。

▼ 作ってみました

Add to Google

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本