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

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


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

こんばんは、うすだです。

最近、文章を書く機会が増えました。

本業でも、仕様を雑把に考えて打合せ資料を作ったり、 設計書を書いたりといった仕事が増えまして、プログラマーのはずが、 ここのところコードをあまり書いていません。
(もちろん、文書作成も仕事だというのはわかっておりますですよ。)

という具合に文章のことを考えていると、必ず思い出すのが、 前の会社で上司に頼まれて書いた論文(の一部)のことです。

ある章をわたしが書き上げ、関係者各位でレビューしたところ、 自分でも笑っちゃうくらい支離滅裂で、ほぼ全部書き直しになりました。
いちおう院卒なので、論文を書いたこともある(はずな)のですが、 目から火が出るくらい恥ずかしい出来でした。

そのとき、自分は文章を書くのが苦手で下手なんだと、確信しました。

にもかかわらず、月日が経ち、こうして各所で文章を書いて、 お前の文章はダメだとあまり言われなくなったのですから、不思議なもんです。

みなさんにも、仕事でダメ出しされることってありますよね。
そんなとき、ああおれってこういうの向いてないな、と思われるかもしれません。 ですが、それでもなんとか続けていると、なにかが蓄積されて、 いつの間にかそうでなくなる日が来るのではないかと思います。

ですので、イヤだなと思うことでも、 いつか苦手でなくなる日が来るかもしれないと思って、続けてみてはいかがでしょうか。

実は、仕様書とか書くのが嫌いなのですが、 早く書き上げないといけない状況にありまして、自分へのエールも兼ねて書いてみました。

次は、もう少し短く簡潔に書けるようにならねば、ということに気づいたところで、 今回もはりきってまいりましょう。

今回のお題 - UPnP でルータを操作してみる

我が家では、実家でご不要になりました古いブロードバンドルータを使用して、 インターネットにつないでいます。

いま調べますと、2004年の製品であることがわかりました。
無線LANは IEEE802.11b のみ対応で、暗号化規格は WEP にしか対応していません。

にもかかわらず、UPnP には対応していました。

UPnP を使いますと、ポートフォワーディングの設定を動的に行うことができます。 また、 NAPTで変換されたグローバルなIPアドレスやポート番号を知ることもできます。
これを利用すれば、内部にあるマシンを、 一時的に外から見せたりなどができるようになりますね。

というわけで今回は、LinuxからUPnP対応の機器(主にルータ)を操作する方法を、 ご紹介したいと思います。

UPnPとは?

まず、UPnP(Universal Plug and Play)について、簡単に説明します。

UPnP とは、家庭内にあるいろんな機器をネットワークにつないだとき、 極力自動的に、相互にやりとりできるようにするための技術です。

イメージ的には、機器をネットワークにぷすっと差して、 それらを直感的にちょちょいと操作できる…というのが理想でしょうか。

そして、UPnPでサービスを提供する機器を「デバイス」、 デバイスを検出して操作するコントローラを「コントロールポイント」と言います。

UPnP で行われる処理を大きく分けますと、以下のようになります。

  1. デバイスをネットワークに接続し、IPアドレスを設定する
  2. デバイスは自分の存在を知らせ、コントロールポイントはデバイスを検出する
  3. コントロールポイントがデバイスの種類を確認して、 デバイスが提供するサービスを使用する

1. では、ネットワークに接続されたデバイスが、DHCP もしくは AutoIP(APIPA(Automatic Private IP Addressing)) により、 IPアドレスなどを自動的に設定します。
(ルータなど、固定のアドレスが設定されている場合は、行いません。)

AutoIP(もしくは APIPA)とは、リンクローカルなアドレスを自動的に設定する機能です。 DHCPとは異なり、サーバが割り当ててくれるのではなく、 個々の機器が空いているIPアドレスを見つけて使うようになっています。
詳しくは、下記の Wikipedia の説明などをご覧ください。

APIPA - Wikipedia
http://ja.wikipedia.org/wiki/APIPA

 

2. では、デバイスは自分の存在をみんなに知らせるため、 コントロールポイントはデバイスを検出するために、 双方がマルチキャストパケットを送信します。

マルチキャストパケットを受信したコントロールポイントやデバイスは、 送信した相手に直接返事をします。

ここでのやりとりは、マルチキャストを扱いますので、UDP を用います。
厳密には、SSDP(Simple Service Discovery Protocol)という HTTPベースのプロトコルを使用します。(ポートは1900番です。)

 

そして 3. では、コントロールパネルがデバイスの種類を問い合わせて、 デバイスの提供するサービスを確認します。
そして、デバイスの状態を確認したり、何らかの操作を行います。

UPnP では、いくつかの種類のデバイスがあらかじめ定められています。
下記に、デバイスとそのサービスの詳細が公開されています。
メディアサーバやブロードバンドサーバ(Internet Gateway)、 プリンタといったありがちなデバイスの他に、日除けやライトなんてのもあります。

Device Control Protocols
http://upnp.org/index.php/sdcps-and-certification/standards/sdcps/

また、ここでは、TCP を用いてやりとりを行います。
厳密には、SOAP(Simple Object Access Protocol)という HTTPベースのプロトコルを用いて通信を行います。(ポートは機器によって違います。)

UPnP を試してみる

UPnPに関する説明がさらっと終わったところで、早速使ってみましょう。

とはいえ、UPnP を試すためのツールが必要ですよね。
今回は、gupnp-tools というパッケージを使って、UPnPを実体験したいと思います。

GUPnP Framework
http://www.gupnp.org/

Fedora や Ubuntu, Debian, OpenSUSE などには gupnp-tools パッケージが標準であるようです。apt や yum などで入手してください。

  # apt-get install gupnp-tools   (Debian系の場合)
  # yum install gupnp-tools       (RedHat系の場合)

 

gupnp-tools をインストールしましたら、 デバイスとなるプロセスを起動してみましょう。
gupnp-network-light という、ライトを模したコマンドがありますので、 これを起動します。

  $ gupnp-network-light
  Attaching to IP/Host 192.168.1.1 on port 36834
  Attaching to IP/Host 127.0.0.1 on port 42710

すると、消灯中のライトのウィンドウが出現します。
そして、待ち受けるIPアドレスとポート番号を、標準出力に出力します。

 

次に、これを操作するコントロールポイントである gupnp-universal-cp を起動します。

  $ gupnp-universal-cp

すると、デバイスをコントロールするためのウィンドウが出現します。
左側に、検出したデバイスの一覧が表示されます。
その中に「GUPnP Network Light」があるはずですので、 先頭の三角形をクリックしてみてください。以下のように展開されます。

  - GUPnP Network Light
    + urn:upnp-org:serviceId:Dimming:1
    + urn:upnp-org:serviceId:SwitchPower:1

Dimming は光量を調節するためのインターフェースですが、 今回は華麗にスルーして、電源スイッチを操作する SwitchPower を試してみます。

まず、SwitchPower の先頭の三角を押しますと、以下のように展開されると思います。

  - GUPnP Network Light
    + urn:upnp-org:serviceId:Dimming:1
    - urn:upnp-org:serviceId:SwitchPower:1
      + State variables
      + SetTarget
      + GetTarget
      + GetStatus

そうしましたら、SetTarget を右クリックして Invoke を選択します。
すると、Action Invocation というダイアログが出現します。
いまは消灯中だと思いますので、 NewTargetValue のすぐ右にある四角をクリックしてチェック状態にして、 右上の Invoke ボタンを押します。

…すると、おお、ライトが点灯します。
同様に、NewTargetValue のチェックを外して Invoke ボタンを押しますと、 お察しの通り、今度はライトが消灯します。

一通り試して気がすみましたら、閉じるボタンを押して戻ります。

次に、GetTarget を試してみましょう。
先ほどと同様に、GetTarget を右クリックして Invoke を選択しますと、 ダイアログが出現します。
ここで、ライトのウィンドウを右クリックして On を選択しますと、 直接ライトのON/OFF を行えますので、お好きな状態に変化させます。
そして、先ほどのダイアログで Invoke ボタンを押しますと、 左下にある RetTargetValue の状態が、ライトの状態に合わせて変化します。

他にも、状態を得たり設定したりするものがいろいろありますので、 試行錯誤してみてください。

もちろん、gupnp-network-light と gupnp-universal-cp は、 同一マシンで動作させる必要はありません。
他に Linux マシンがありましたら、別々に起動して、 同じように操作が行えることを確認してみると、なおいっそう楽しい(?)と思います。

UPnP でルータを操作してみる

さて、UPnP を擬似的に試したところで、 今度はホンモノの UPnP 機器を操作してみたいと思います。
具体的には、ルータに対して、ポートフォワーディングの設定を行いたいと思います。

とはいえ、セキュリティ的に微妙な例も含まれますので、 リスクや効果を十分吟味された上で、自己責任でお試しいただければと思います。
(逃げ口上的で申し訳ございません…。)

さて、先ほどの gupnp-universal-cp のウィンドウの左側のデバイス一覧に、 「WANConnectionDevice」というものがありますでしょうか。
もしありましたら、それが UPnP 対応のルータです。

あ、ひょっとすると違う名前かもしれません。 これかなと思われるモノがありましたら、クリックして、 右側に表示される情報を眺めてみます。
Type に WANConnectionDevice という文字があったり、 Manufacturer や Model Description などがそれっぽい場合は、おそらくルータです。

ありましたら、先ほどと同様に、先頭の三角をクリックしてみましょう。

  - WANConnectionDevice
    + urn:upnp-org:serviceId:wanetherlinkconfig1
    + urn:upnp-org:serviceId:WANCableLinkConfig1
    + urn:upnp-org:serviceId:wanipconnection1

さて、今回の目的はポートフォワーディングですので、展開された3つのうち、 一番下の wanipconnection1 をさらに展開します。

  - WANConnectionDevice
    + urn:upnp-org:serviceId:wanetherlinkconfig1
    + urn:upnp-org:serviceId:WANCableLinkConfig1
    - urn:upnp-org:serviceId:wanipconnection1
      + State variables
      + SetConnectionType
      ...中略...
      + AddPortMapping
      + DeletePortMapping
      + GetExternalIPAddress

ポートフォワーディングの追加は AddPortMapping で行えますが、 唐突に試す前に、まず GetExternalIPAddress で、 ルータの WAN側のIPアドレスを確認しておきましょう。
GetExternalIPAddress を右クリックして Invoke を選び、Invoke ボタンを押すと、 NewExternalIPAddress にIPアドレスが表示されます。

このアドレスをどこかにメモっておいてから、 先ほどの AddPortMapping を Invoke して、以下のように引数を設定します。

  NewRemoteHost     : (GetExternalIPAddress で得たIPアドレス)
  NewExternalPort   : 2022 (ここでは仮にそうしておきます)
  NewProtocol       : TCP
  NewInternalPort   : 22 (ここでは仮に…略)
  NewInternalClient : (ご使用のLinuxマシンのIPアドレス)
  NewEnabled        : (チェックします)
  NewPortMappingDescription : (お好きな文言を)
  NewLeaseDuration  : 0 (0以外だとエラーになりました)

申し遅れましたが、外部から、現在ご使用のマシンに対して、 SSH で遠隔ログインするためのポートフォワーディングの設定です。
具体的には、外のマシンからルータの2022番に対して SSH で接続しようとすると、 それがお使いのマシンの22番(SSHですね)にフォワーディングされます。

さて、上記を入力しましたら、Invoke ボタンを押します。
何も文句を言われなければ、おそらく設定が成功しています。

ホントウに成功したか気になる貴兄は、GetGenericPortMappingEntry を Invoke し、 NewPortMapping に 0 を設定して Invoke を押しましょう。
NewRemoteHost 以降に、先ほど設定した値が入っていると思います。

 

さて、ホントにポートフォワーディングが設定されているか、 確かめないといけないですよね。
そのためには、 ルータの外の世界にあるどこかのマシンに遠隔ログインをする必要があります。
そして、そのマシンから、先ほどの NewRemoteHost の NewExternalPort に対して、 SSH による遠隔ログインを試みます。

  ext$ slogin -p 2022 (GetExternalIPAddressで得たIPアドレス)
  usu@(GetExternalIPAddressで得たIPアドレス)'s password:
  ...中略...
  Welcome to Ubuntu!

  Last login: Fri Jun 11 23:14:45 2010 from wonderland
  int$

ログインできて、ログインしたマシンが、いままさに使っているマシンであれば、 ポートフォワーディングが設定されていることになります。

試した後は、ポートフォワーディングの設定を外しておきましょう。
DeletePortMapping を Invoke して、引数を以下のように設定してから、 Invoke ボタンを押します。

  NewRemoteHost     : (GetExternalIPAddress で得たIPアドレス)
  NewExternalPort   : 2022
  NewProtocol       : TCP

何も言われなければ、成功しているはずです。
実際、先ほどと同じように GetGenericPortMappingEntry で確認すると、 以下のようなアラートが表示されるはずです。

  Action failed.
  Error 713: SpecifiedArrayIndexInvalid

おわりに

以上、UPnP を使って、なんちゃってライトやルータを操作する方法を、 おおまかにご紹介しました。

実は、UPnPがどの程度普及しているのか、よく知りません。(スミマセン)
ですが、調べてみたところ、Linux にもいくつかツールがありますので、 それなりに普及しているのではないかと思われます。

ルータ以外にもUPnPな機器がありましたら、 セキュリティを気にしながらいろいろ操作してみてくださいませ。

宿題の答え

前回の宿題は、

  mktempコマンドが安全であることを確認してみましょう。

でした。

生成される可能性のあるファイルを事前に作成しておき、 mktempコマンドを実行したときに、 それらとかぶらない(エラーになる)ことを確認したいと思います。

作成する前に、どのくらいのファイルを作らないといけないのか、 簡単に見積もっておきましょう。

ひとつの X に対して、 大小を含む英数字62パターン(a〜z,A〜Z,0〜9)の可能性があります。 で、たとえば X が5つあると、

  62 × 62 × 62 × 62 × 62 = 916,132,832

…という具合に、9億個以上のファイルが必要になります。

環境によるかもしれませんが(本当?)、億単位では無理っぽいですので、 X の数は、1個か2個、多くても3個くらいで試したいと思います。

…と思ったのですが、どうやら3個でやってみるしかなさそうです。

  $ mktemp /tmp/test-X
  mktemp: too few X's in template `/tmp/test-X'
  $ mktemp /tmp/test-XX
  mktemp: too few X's in template `/tmp/test-XX'
  $ mktemp /tmp/test-XXX
  /tmp/test-r0P

もちろん、X が3個でも、62 × 62 × 62 = 238,328 個必要です。
1個ずつ手で作っていては、1秒に1個のペースでも、不眠不休で3日弱ほどかかります。 ですので、以下の Perl スクリプトに作っていただきます。

  #!/usr/bin/perl
  my @randchars = ('0'..'9' , 'a'..'z' , 'A'..'Z');
  foreach my $s1 (@randchars) {
      foreach my $s2 (@randchars) {
          foreach my $s3 (@randchars) {
              symlink("/dev/null", "/tmp/181test-$s1$s2$s3");
          }
      }
  }

このスクリプトは、mktemp /tmp/181test-XXX で作成される可能性のあるファイルを、 /dev/null を指すシンボリックリンクで作成し尽くします。
いつものごとく、紙面の都合によりコードの説明は割愛いたします。

これを、たとえば mkbadtemp.pl というファイル名で保存したら、 いつものように実行の権限をつけて実行します。

  $ chmod +x mkbadtemp.pl
  $ ./mkbadtemp.pl

自動とは言え、それなりに時間がかかります。
ファイルシステムに不安を感じていたり、CPUが滅法非力な場合は、 実行しないほうが賢明かもしれません。

さて、スクリプトの実行が終わりましたら、mktemp コマンドを実行してみましょう。

  $ mktemp /tmp/181test-XXX
  mktemp: failed to create file via template `/tmp/181test-XXX': \
  File exists

…おお、余地がないので作成できませんでした。(成功です!)
ここで、1つだけ消し去ってみましょう。

  $ rm /tmp/181test-ABC
  $ ./mktemp /tmp/181test-XXX
  /tmp/181test-ABC

今度は、ピンポイントで生成されました。(当たり前ですが)
というわけで、まあ、安全だと言えるのではないでしょうか。

さて、一通り試した後は、ファイルを消しておきましょう。
ただし、わたしの環境では、ファイルの数が多すぎて叱られました。

  $ rm /tmp/181test-*
  bash: /bin/rm: Argument list too long

こんなときは、地道に、分割して消せばよろしいかと思われます。
(ところで、bash が扱えるファイル数の上限はいくつなんでしょう…。)

  $ rm /tmp/181test-[A-Z]*
  $ rm /tmp/181test-[a-z]*
  $ rm /tmp/181test-[0-9]*

今回の宿題

今回の宿題は、

  UPnP でやりとりするパケットを眺めましょう。

です。

tcpdump や wireshark など、 パケットをキャプチャするツールを使って UPnP のパケットを取得してみましょう。

そして、中のデータがどうなっているか、さらっと確認してみると、 どういうやりとりをしているのかがおぼろげにわかるのではと思います。
(HTTPベースなので比較的わかりやすいのでは? という魂胆です。)

あとがき

前回に引き続き、セキュリティに関して興味を持ちつづけています。

さて、今回ご紹介するのは、 情報収集としてもお勉強のきっかけとしても重宝している 「CodeZine(コードジン)」というサイトの以下の連載です。

実例で学ぶ脆弱性対策コーディング : CodeZine
http://codezine.jp/article/corner/372

オープンソースなどで実際に発見された脆弱性とその修正方法を、 ソースコードの抜粋とともに、わかりやすく教えてくださいます。

前回ご紹介した「Jarlsberg」も、 まず自分で考えてから答えを見る形式になっていました。
この連載も、脆弱性が発見されたソースコードの抜粋がまず示されます。
ですので、自分なりの答えを考えてから読み進めますと、いっそう勉強になるぜぇ、 という形態になっています。

それにしても、普段、オーバーフローや NULL ポインタ、 引数などに気をつけているつもりでしたが、どこに問題があるかと言われると、 なかなかわからないものですね。ちょっと自信をなくしました。

個人的には、脆弱性の修正方法が興味深かったです。
実は、今の今まで、fread() や fwrite() の引数がなぜああなっているのか、 恥ずかしながら知りませんでした。勉強になりました。
(理由を知りたい貴兄は、バックナンバーを逐一ご覧くださいませ。)

 

それから、CodeZine には、息抜き的な連載もいくつかあります。
その中でも、「風雲!ITおじさん」は、わたしのお気に入りです。
絵がなんともな感じですが、先入観を捨ててご覧くださいませ。

風雲!ITおじさん : CodeZine
http://codezine.jp/article/corner/210

 

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

 

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

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

「栗日記」- 今日で3100枚に達しますが、最近描いているだけです。
http://www.usupi.org/kuri/ (まぐまぐ ID:126454)
http://usupi.seesaa.net/ (栗日記ブログ)
http://usupi.org/k/ (モバイル栗日記)


[バックナンバーのトップへ] [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

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本