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

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


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

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

この春、 情報処理技術者試験のエンベデッドシステムスペシャリスト試験を受験したのですが、 先月の25日に、ネットで合否が発表されました。

事前の答え合わせでは、なんとも微妙な感じだったので、 どうしてもよい結果を期待してしまっていたのですが、その結果はと言いますと…

 

 

 

 

…はい、落ちてました。OTZ

しかも、一番できの悪かった午後I が59点で、1点足りませんでした。
(午後II は採点されていませんので、 午後II がもっと悪かった可能性は否定できませんが…。)

もう、昔から、詰めが甘い甘いと言われて育ってきたのですが、またここでも、 詰めの甘さを発揮してしまったようです。

ところで、過去、詰めの甘さが一番際立ったのは、大学受験のときです。
5つ受けてすべて落ちたのですが、その後2つ追加(補欠で)合格しました。
このときは、ギリギリの神様が、お情けで合格させてくれたのではないかと思っています。

じゃあ今回はと言うと、おそらく、ちょっと勉強しただけで合格すると、 図に乗ってしまい、 後で本人が痛い目に会うとかわいそうだと(ギリギリの神様が)思って、 落としてくれたのだと思います。

ええ、そう思うことにします。そう思いますとも。
来年もトライして、もう少し前もって勉強しておこうと思います。

…ええ、ショックじゃありませんから、今回もはりきってまいりますよ!

今回のお題 - Linux を UPnP 対応にする

Linuxマシンを使ってインターネットにつないでいたり、 社内LANから存在していない(ことになっている) ネットワークを Linux マシンでこっそりつないだりなど、 Linux をルータとして使用するケースが、意外とあるのではないかと推測しております。

どちらの場合も、内部のネットワークを外に見せるわけにはいきません。
ですので、IPマスカレード(NAPT)やポートフォワーディングなどで、 内部の存在を隠蔽されているのではないかと思います。

しかし、そんなときに困るのが、ポートフォワーディングの設定ではないでしょうか。

ユーザさまから、ちょっとこのポートで外からつながるようにしてほしいんだけど、 とお願いされる度に、設定を追加したり削除したりするのは、骨が折れますよね。

会社のポリシーにもよりますが、柔軟な(悪く言えば放置主義的な)ところであれば、 ユーザさまに、それらの設定を行ってもらえば、管理者の貴重な骨を温存できそうです。

というわけで今回は、Linux マシンを UPnP 対応のルータにしてみたいと思います。

とりあえず動かす

Linux を UPnP 対応ルータに仕立て上げるには、linux-igd パッケージを使用します。

Ubuntu や Debian, Fedora などの主要なディストリビューションには、 もれなく用意されているようですので、 いつものように yum や apt などを使ってインストールしてください。

  # yum install linux-igd      (RedHat 系の場合)
  # apt-get install linux-igd  (Debian 系の場合)

設定ファイルは、以下にあります。 ディストリビューションによってパスが異なりますが、記述すべき内容はほぼ同じです。

  /etc/sysconfig/upnpd    (RedHat 系の場合)
  /etc/default/linux-igd  (Debian 系の場合)

最小限的には、 外側と内側のネットワーク・インターフェースをそれぞれ指定するだけです。 具体的には、外側のインターフェースを EXTIFACE で指定し、 内側のインターフェースを INTIFACE で指定します。

たとえば、外側が eth1 で内側が eth0 なら、以下のように記述します。

  EXTIFACE=eth1
  INTIFACE=eth0

あとは、以下の手順で、デーモンを起動するだけです。
起動すると、upnpd というデーモンが動作するようになります。

  # /etc/init.d/upnpd start      (RedHat 系の場合)
  # /etc/init.d/linux-igd start  (Debian 系の場合)

upnpd は、UPnP からの依頼を受け付け、 ポートフォワーディングなどの設定を iptables コマンドを利用して行います。

 

基本的な設定は、これだけで OK なはずです。

ただ、ファイアーウォールの設定がされている場合、 うまくつながらない可能性があります。(というか、たぶんつながりません。)

ですので、UPnPを許可する必要がありますが、 ポート番号が決まっているわけではないため、 UPnPだけ許可させるのはかなり難しいように思います。
ですので、ここは男らしく(?)、 内側のインターフェースに対する制限を全部なくしてしまいましょう。
(もちろん、会社の許可が得られなければ、できませんが…。)

GNOMEのメニューから、「システム」-「管理」-「ファイアーウォール」を選択して、 「ファイアーウォールの設定」を起動します。
次に、「信頼したインターフェイス:」を選び、 内側のインターフェースのところにチェックを入れて、「適用」を押します。

以上で、UPnP がつながるようになるのではないかと思います。

 

…おっと、あと忘れがちなのが、IPフォワーディングの設定です。
IPフォワーディングを有効にしていないと、NATが動作しません。
いえ、すでにルータとして使用されている場合は、設定がされているはずですが、 念のためお知らせしておきます。

以下のように、procfs で直接設定してもよいですし、 sysctl コマンドを使って設定することもできます。
いずれの場合も、1 で有効に、0 で無効に設定します。

  # echo 1 > /proc/sys/net/ipv4/ip_forward
  もしくは
  # sysctl -w net.ipv4.ip_forward=1

動作確認してみる

upnpd が走り始めたところで、実際に設定できるか確認してみましょう。
といっても、手順は、前回お知らせした内容の通りです。
(ご存じの貴兄は、次の節まですっ飛ばしてくださいませ。)

Vol.181 - UPnP でルータを操作してみる
http://www.usupi.org/sysad/181.html

まず、内側のネットワーク上のマシンで、gupnp-universal-cp コマンドを実行します。

すると、出現したウィンドウの左側に、検出したデバイスが表示されますので、 その中に「WANConnectionDevice」があることを確認します。

ありましたら、先頭の三角をクリックして、順に展開していきます。

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

ポートフォワーディングの設定を行うためには、 「AddPortMapping」を右クリックして「Invoke」を選びます。
そして、以下のように引数を指定して、「Invoke」ボタンを押します。

  NewRemoteHost     : (ルータの外側のIPアドレス)
  NewExternalPort   : (外からつなげられるルータのポート番号)
  NewProtocol       : (TCP もしくは UDP)
  NewInternalPort   : (フォワード先の内部のマシンのポート番号)
  NewInternalClient : (内部のマシンのIPアドレス)
  NewEnabled        : (否応なくチェック)
  NewPortMappingDescription : (お好きな文言を記述)
  NewLeaseDuration  : (使用する期間を秒で指定)

たとえば、以下のように設定して「Invoke」したとしましょう。
(外部のどこかから 115.146.17.162 のポート 1080 にTCPで接続すると、 192.168.1.1 のポート 80 につながる、という寸法です。)

  NewRemoteHost     : 115.146.17.162  (←これはあくまで例ですよ)
  NewExternalPort   : 1080
  NewProtocol       : TCP
  NewInternalPort   : 80
  NewInternalClient : 192.168.1.1
  NewEnabled        : (チェック)
  NewPortMappingDescription : Internal web server
  NewLeaseDuration  : 1800

そうしましたら、UPnP対応のルータで、以下のように iptable コマンドを実行します。

  # iptables -nL
  Chain INPUT (policy ACCEPT)
  target     prot opt source           destination

  Chain FORWARD (policy ACCEPT)
  target     prot opt source           destination
  ACCEPT     tcp  --  0.0.0.0/0        192.168.1.1     tcp dpt:80

  Chain OUTPUT (policy ACCEPT)
  target     prot opt source           destination

このように、FORWARDチェインに追加されていることがわかります。

具体的に確認するには、外側のマシンから以下にアクセスします。

  http://115.146.17.162:1080/

内側のマシン 192.168.1.1 が提供する WWW のページが表示されることを確認してください。

 

上記の場合は、NewLeaseDuration に 1800秒を指定しましたので、 30分後に設定が消えますが、それまでに消したい場合や、 NewLeaseDuration を指定しなかった場合は、 DeletePortMapping で消し去る必要があります。

手順は同様で、「DeletePortMapping」を右クリックして「Invoke」し、 以下のように引数を設定して「Invoke」ボタンを押します。

  NewRemoteHost     : (ルータの外側のIPアドレス)
  NewExternalPort   : (ルータのポート番号)
  NewProtocol       : (TCP もしくは UDP)

先ほどの例にそって具体例を示しますと、以下の通りです。

  NewRemoteHost     : 115.146.17.162
  NewExternalPort   : 1080
  NewProtocol       : TCP

同様に iptables コマンドを実行して、設定が消去されたことを確認することができます。

  Chain INPUT (policy ACCEPT)
  target     prot opt source           destination

  Chain FORWARD (policy ACCEPT)
  target     prot opt source           destination

  Chain OUTPUT (policy ACCEPT)
  target     prot opt source           destination

 

上記で問題なければ、あとは起動時に upnpd が動作するよう仕込むだけです。 (必要であれば…ですが。)

RedHat 系の場合は、chkconfig コマンドで登録します。

  # chkconfig upnpd on

Debian 系の場合は、EXTIFACE と INTIFACE が設定されていれば、 起動時に upnpd が動作しますので、特に設定する必要はありません。
(逆に、起動してほしくない場合は、 EXTIFACE もしくは INTIFACE の設定を消しておく必要があります。)

セキュリティを考慮してみる

さて、基本的な設定と確認はご紹介し終わりました。
ですが、最後に、セキュリティに少しだけ気を使ってみたいと思います。
ただし、以降は Debian 系に限られます。ご了承ください。

Debian 系の場合、設定ファイルである /etc/default/linux-igd には、 EXTIFACE と INTIFACE の他にも、いくつか設定の項目があります。

その中に、非root ユーザの権限で upnpd を動作させるための設定項目があります。 それが UPNPD_USER です。
UPNPD_USER を設定しますと、root でないユーザで upnpd を動作させることができます。

では、実際に試してみましょう。

まず、非root なユーザとグループを作成します。
ここでは仮に、igd という名前のユーザとグループを作成します。
以下では、groupadd コマンドで igd グループ、 useradd コマンドで igd ユーザを作成しています。 UID も GID も 254 にしていますが、実際には使用されていない ID を指定してください。

  # groupadd -g 254 igd
  # useradd -u 254 -g 254 -d /etc/linuxigd -s /bin/false igd

ただ、upnpd を動作させるには、各所で root の権限が必要になります。
ですので、ここでは、ケーパビリティという機構を利用します。
ケーパビリティは、root の権限を細かく分けて、 その細かい権限を必要最小限だけ与えることで、 セキュリティを向上しようというものです。

今回は、細かい説明を省きまして、設定方法だけを簡単にご紹介します。
(ケーパビリティについては、いつかネタにしますので、 それまで気長にお待ちいただけますと幸いです。)

ケーパビリティの設定には setcap コマンド、参照には getcap コマンドを使用します。 これらは libcap2-bin パッケージにありますので、 もしなければ、インストールしておいてください。
(ちなみに Fedora などの場合は、libcap パッケージです。)

で、upnpdの所有者を igd にして、igd だけが実行できるようにします。
そして、upnpd に対して、ネットワークの各種操作を許すようにします。

  # chown igd.igd /usr/sbin/upnpd
  # chmod go-rwx /usr/sbin/upnpd
  # setcap cap_net_admin,cap_net_raw=ep /usr/sbin/upnpd
  # getcap /usr/sbin/upnpd
  /usr/sbin/upnpd = cap_net_admin,cap_net_raw+ep

最後の getcap コマンドは、設定の確認のために実行しているだけです。

また、upnpd は iptables コマンドを実行しますが、 iptables コマンドの実行にも root 権限が必要です。
ここでは、igdユーザ専用の iptables コマンドを /etc/linuxigd に作成して、 これもネットワークの各種操作ができるよう権限を与えます。
(別に /etc/linuxigd でなくても、他のディレクトリでも構いません。)

  # cp -p `which iptables` /etc/linuxigd/iptables
  # chown igd.igd /etc/linuxigd/iptables
  # chmod go-rwx /etc/linuxigd/iptables
  # setcap cap_net_admin,cap_net_raw=ep /etc/linuxigd/iptables
  # getcap /etc/linuxigd/iptables
  /etc/linuxigd/iptables = cap_net_admin,cap_net_raw+ep

そして、upnpd が上記の iptables を呼び出すよう、 /etc/upnpd.conf の以下の行を書き換えます。

  iptables_location = "/sbin/iptables"
  を以下に変更
  iptables_location = "/etc/linuxigd/iptables"

そして、upnpd を起動(再起動)すると、igd ユーザの権限で走行するようになります。

  # /etc/init.d/linux-igd start (再起動の場合は restart)

 

他にも、chroot して起動させる設定項目などがありますが、 今回は確認しているヒマがありませんでした。すみません。
また別の機会にご紹介したいと思います。

おわりに

以上、Linux をUPnP対応ルータに仕立て上げる方法を、ご紹介しました。

まあ、実際問題として、UPnP を会社に導入するのは、 あまり許されないことのように思います。

ここは、Linux でもそんなことができるんだ、というくらいの気持ちで、 さらっと読んでいただければと思います。
(あわよくば、ご自宅などで試していただけますと、感謝感激です。)

宿題の答え

前回の宿題は、

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

でした。

IPアドレスが 192.168.1.211 の PC で gupnp-universal-cp を起動し、 IPアドレスが 192.168.1.254 のルータとやりとりするところを、 tcpdumpコマンドで取得してみました。

以下のように、upnp_bb_router.log というファイルに、 キャプチャしたデータを記録しています。
(場合によっては、関係ないパケットも含まれます。)

  # tcpdump -s 1500 -w upnp_bb_router.log host 192.168.1.211 or \
  host 192.168.1.254

それでは、以下のように実行して、中身を参照してみましょう。

  # tcpdump -n -X -s 1500 -r upnp_bb_router.log | less

…とはいえ、やはり見づらいですので、こちらでよきように清書したものを、 以下に示していきます。

 

まず、コントロールポイントである 192.168.1.211 からマルチキャスト (239.255.255.250:1900)で問い合わせるUDPパケットの中身です。

  M-SEARCH * HTTP/1.1
  Host: 239.255.255.250:1900
  Man: "ssdp:discover"
  ST: upnp:rootdevice
  MX: 3
  User-Agent: gupnp-universal-cp GSDP/0.7.1

最初の行は、機器を探していますよというお約束的なもので、 2〜3行目もお約束的な文言です。(ので割愛します。)
ST: は Search Target の略で、対象のデバイスを指定します。
どうも、UPnP ではデバイスの中にデバイスがあってもよいようで、 ここでは rootdevice を指定していますので、 一番外側(親)のデバイスだけに限定しているようです。
MX: は Maximum wait time の略で、最大でこの秒数待ちますよと言っているようです。

次に、ルータである 192.168.1.254 からの返事です。
これはマルチキャストではなく、直接 192.168.1.211 に返しています。

  HTTP/1.1 200 OK
  CACHE-CONTROL: max-age=30
  EXT:
  LOCATION: http://192.168.1.254:5431/upnp/igdevicedesc.xml
  SERVER: UPnP/1.0 <製品名>/<バージョン>
  ST: upnp:rootdevice
  USN: uuid:01234567-89ab-cdef-0123-456789abcdef::upnp:rootdevice

最初の HTTP 云々は、HTTP ではおなじみの文言ですね。
EXT: は、UPnP 1.0 との互換性のためにつけられるものだそうです。
SERVER: には、UPnPのバージョン、製品とそのバージョンが入ります。
(おっと、このルータは UPnP 1.0 にしか対応していませんね…。)
USN は Unique Service Name の略で、 これによりサービスを一意に指定することができるようです。

 

それでは、次のパケットを眺めてみましょう。
今度は、192.168.1.211 から 192.168.1.254:5431 に対して、 TCP で通信を行っています。

  GET /upnp/igdevicedesc.xml HTTP/1.1
  Host: 192.168.1.254:5431
  User-Agent: gupnp-universal-cp GUPnP/0.13.2 DLNADOC/1.50
  Accept-Language: ja-jp;q=1, ja;q=0.5

接続先の 192.168.1.254:5431 と GET で指定したパスは、 先ほど返ってきた応答の LOCATION: がもとになっています。
そして、それに対する 192.168.1.254 の返事が以下です。

  HTTP/1.1 200 OK
  SERVER: UPnP/1.0 <製品名>/<バージョン>
  DATE: Wed, 29 Aug 2007 07:59:06 GMT
  CONTENT-TYPE: text/xml
  CONNECTION: close

  <?xml version="1.0"?>
  <root xmlns="urn:schemas-upnp-org:device-1-0">
    <specVersion><major>1</major><minor>0</minor></specVersion>
    <URLBase>http://192.168.1.254:5431/</URLBase>
    <device>
      <deviceType>
      urn:schemas-upnp-org:device:InternetGatewayDevice:1
      </deviceType>
    ...以下、長いので略...
    </device>
  </root>

ようするに、どんなデバイスなのか問い合わせているようです。
XMLの形式でいろいろな情報が返ってくるのですが、 deviceType でルータだということがわかる、というのが大きな収穫だと思います。

 

あと、ExternalIPAddress を得るところを見ておきましょう。
TCP でといいますか、HTTP でといいますか、SOAP で問い合わせているのですが、 見た通りだと思いますので、説明は割愛します。

  POST /WANCONNECTION/WANIPConnection HTTP/1.1
  Host: 192.168.1.254:5431
  SOAPAction: "urn:schemas-upnp-org:service:WANIPConnection:1#\
  GetExternalIPAddress"
  ...中略...

  <?xml version="1.0"?>
  <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
   s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <s:Body>
      <u:GetExternalIPAddress
       xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
      </u:GetExternalIPAddress>
    </s:Body>
  </s:Envelope>

これに対するルータの返事は、以下の通りです。

  HTTP/1.1 200 OK
  CONTENT-TYPE: text/xml; charset="utf-8"
  ...中略...

  <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
   s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <s:Body>
      <u:GetExternalIPAddressResponse
       xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
        <NewExternalIPAddress>1.2.3.4</NewExternalIPAddress>
      </u:GetExternalIPAddressResponse>
    </s:Body>
  </s:Envelope>

長いですが、要約すると、1.2.3.4 ですよとおっしゃっていますね。

 

以上、長々と説明してしまいました。
といっても、やはり、大幅に省略させていただいています。
もし万が一、UPnP について詳しく知りたい場合は、 以下から仕様を入手してくださいませ。(英語ですが、斜め読める内容です。)

Device Architecture Documents >> UPnP Forum
http://upnp.org/index.php/sdcps-and-certification/standards/device-architecture-documents/

今回の宿題

今回の宿題は、

  iptables の設定が変更されたらメールで通知するようにしましょう。

です。

linux-igd によって、 自由に設定変更してください的なポリシーで運用がなされるようになると思います。 ですが、管理者は一切関与しませんよ、と責任を放棄するわけにもいかないのが、 つらいところです。

というわけで、 ユーザが設定変更(ポートフォワーディングの設定を追加したり削除したり) を行ったときに、その旨をメールで知ることができるとよいのではないか、 と思った次第です。
(ありきたりですが…じゃあ、 「メールで通知」をなにかに置き換えればいろんなことができる、 ということでご容赦くださいませ。)

あとがき

ちょっと前に、「ヘッテルとフエーテル」という本を読みました。

ヘッテルとフエーテル
http://www.amazon.co.jp/exec/obidos/ASIN/4766784588/usupiorg06-22

金融にまつわるワナや裏側などを、物語形式でわかりやすく教えてくれる本です。 金融にまつわるダークなことが、物語でさらりと書かれていますので、 1時間足らずで読めました。

知っていることもいくつかありましたが、あらためて、 鵜のみにしていてはいけないということを再認識することができました。

さて、上記の転職版的な物語が、「CAREERzine」に掲載されていました。
本の物語と同レベルの内容が無料で読めますので、ここに紹介します。
(いま参照したら、ログインが必要でした。もちろん登録は無料です。)

本当に残酷な転職マネー版グリム童話「幸せをあおる虫」
「『好き』を仕事に」の教祖様と信者の関係
http://careerzine.jp/article/detail/1144

好きなことを仕事にして裕福になろう、と提唱するある著名人を、 面白くかつ少しせつなく、やり玉に挙げています。

わたしは、(元ネタと思われる)著名人の本を何冊か読んで、 特に疑いなど抱いていませんでしたので、 ターゲットにされたことがショックでした。
(それにしても、「ほんだら拳法」って…危なすぎるなぁ…www。)

ですが、指摘されていることもたしかに一理あります。
人間、言われたことを素直に受け入れることも大事ですが、 自分で考えて判断することも大事だなと思いました。

ただ問題なのは、どうすれば成功したりよい方向に進んでいけるのかが、 さっぱりわからなくなってしまうことです。

なんだか、裕福や幸せを追い求めても、手に入れるのは難しいんだよ、 と言われている気がしてしまいます。なんだかなぁ…。(-ε-;;

 

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

 

「いますぐ実践! 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/ (モバイル栗日記)


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

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本