今日からCGIプログラマー 《第3回》ローカルサーバを公開する ネットワークの知識が不可欠。意地でも公開。あとには楽園。 大きな野心 実は、この連載には大きな野心がある。それは、「もはや、CGIはプロバイダのサ ーバに置くものではない」というコンセプトだ。言い換えると、「CGIを自宅のWi ndowsで稼働すると、こんなに新鮮で便利なの〜?!」ということだ。これが、多 くのCGI入門と、まるで異なる部分である。 これまでの連載のように、「スタンド・アロンWebサーバ+CGI」でも、面白い ことがたくさんできる。しかし、ローカルWebサーバを外に公開したとたんに、でき ることの幅が星の数ほど増える。 たとえば、ほんの一例だが、ごく気軽に、携帯電話から自分のマシンのデータや、マ シンそのものを管理することもできるのだ! そこで、今回は、@Windowsで構築したローカルWebサーバを、意地でも外 に公開したい。 また、Aそれを特定の人間にだけ公開する手法を少し見る。 大急ぎで見るので、不明な点は、ネットや書籍などで調べてほしい。 ローカルIP空間 多くのADSLモデムやブロードバンド・ルータでは、ゲートウェイ(そのルータ自 身のアドレス)が、「192.168.0.1」となっている。この数字は何か。 「ローカルIP」と「グローバルIP」という言葉は聞いたことがあるだろう。「1 92.168.0〜255.0〜255」は、簡単にいうと、定められたローカルIP の1つだ。 インターネット・サービスは、「IPアドレス」という数字を主体に動いていて、そ の数字にドメイン名を結びつけてある。その証拠に、「http://www.koh gakusha.co.jp/」「http://61.120.37.205/」を ブラウザで表示させると、どちらも同じページが表示される。 これは、同じものが2つあるのではなく、後者のほうが、インターネットの主体のア ドレスで、前者は、それに人間が分かりやすいように名前が振ってあるだけなのだ。 この後者のアドレスは「グローバルIP」で、企業やプロバイダなどが、ある手続き を経て、固有のアドレスを借りている。ADSLモデムがインターネットに接続される と、必ず、1つのグローバルIPが、プロバイダから割り振られる。 これだけだと、モデム1つに、マシン一台しか接続できないので、モデムは2つ(以 上)のアドレス空間をもてるようになっている。外のアドレス空間である「グローバル IP空間」(インターネット)と、内側のアドレス空間である「ローカルIP空間」( LAN)である。 ルータやモデムは、この「グローバル空間」と「ローカル空間」を橋渡ししてくれる のだ。 通常は、「192.168.0.1」と、サブネット・マスク「255.255.2 55.0」でよい。 まずは、このモデムのLAN側IPアドレス設定を確認してほしい。最近のモデムは 、たいてい、Webベースで管理できるようになっているので、確認の方法は、マニュ アルを見れば分かるだろう。 バイバイDHCP たいていのモデムは、デフォルトで、DHCPを有効にしているだろう。「DHCP 」とは、各Windowsマシン(ローカル・マシン)にローカルIPを自動的に割り 振る仕組みである。 これにより、ローカルのWindowsマシンは、何も設定しなくても、モデムから インターネットに接続できる。しかし、ローカルWebサーバ(Windowsマシン )には、明示的に固定IPアドレスを設定してほしい。 なお、USBタイプのADSLモデムの場合、複数のマシンの接続を想定していない ため、このような設定をしなくてもよいかも知れない。 では、ローカルWebサーバの設定である。もし、モデムを「192.168.0. 1」にしたなら、固定IPアドレスは、素直に「192.168.0.2」にするとよ いだろう。サブネット・マスクは「255.255.255.0」。デフォルト・ゲー トウェイとDNSサーバは、モデムと同じ「192.168.0.1」とする。 (具 体的な設定方法は、検索エンジンで、「IPアドレス」「設定」「Windows」の 3つのキーワードで検索をかければ、いくらでも書いてあるので参照されたい)。 次にADSLモデムの設定である。Webサーバ・マシンは固定IPアドレスを振っ たとしても、ノートパソコンや他のマシンなどは固定にしたくない場合もあろう。そん なときは、ADSLモデムのDHCPの設定を細かくカスタマイズするとよいだろう。 その考え方だが、これまでのような設定だった場合、ADSLモデムのDHCPには 「192.168.0.100〜120」を割り当ててはどうか。これにより、固定I Pマシンを「192.168.0.3〜99」の範囲で自由に増やすこともできる(G WとDNSは、モデムと同じ「192.168.0.1」。詳しくはマニュアル参照) 。 以上により、ローカルWebサーバは固有のIPになり、他のマシンは、特に設定を しないでもDHCPの機能により、インターネットが使えるようになる。 いよいよ公開 このままでは、ローカルWebサーバは、外からは見えない。公開しよう。公開とい っても、すでにperlとApacheのインストールが終わっている読者にとっては 、造作もないことである。 それには、ADSLモデムの「スタティックIPマスカレード」、もしくは、それに 準ずる設定をする。外からモデムに対して、ポート80番にアクセスがあった場合、ロ ーカルIPアドレス「192.168.0.2」のポート80番に対してそれを行なう ようにすればよいのだ。写真は、TCPプロトコルの開始80〜最終80ポートに対し 、「192.168.0.2」を割り当てている。ところが、困ったことに、これのできないモデムがある。 USBタイプのADSLモデムなど、本体にこのような機能がないモデムである。Y ahoo BBなどはこのタイプのモデムを支給している。 そのような場合は、フリーのパーソナル・ファイヤアウォールを試せば、ある程度問 題は解決するかもしれない。 「TINYSOFTWARE」は自宅での利用は無償で、「ZoneAlarm」は 個人と非商用の利用は無償だという。どちらを使ってもよいだろう。 2つのソフトに関する情報や設定などは、「http://www.ocn.ad. jp/security/pw/index.html」に詳しい。 モデムのセキュリティ機能を切って、セキュリティをパーソナル・ファイヤアウォー ルに任せれば、上手くいくかもしれない。 スクリプト そんなわけで、実験的に作ったのが、リスト1である。これを、「c:\perl\ cgi」などの、Webサーバで設定した「cgi-bin」フォルダに格納する。 この状態でWebサーバを起動し、「http://192.168.0.2/cg i-bin/s.pl」を表示させる。ローカルLAN内にあるマシンなら、どのマシ ンからも同じように表示されるだろう。 どのようなブラウザ(エージェント)でアクセスしてきたかは、「$ENV{'HT TP_USER_AGENT'}」を調べることで、また、どのようなIPアドレスで アクセスしてきたかは、「$ENV{'REMOTE_ADDR'}」で分かる。 スクリプトでは、さらに、IPアドレスからリモート・ホストを調べている。 これを元に、 @J-PHONE端末か、IEか、NN AローカルLANからのアクセスか、J-Phoneのネットワークか、ニフティのp pp の二つの条件を満たしたときに、パスワードのチェックに進むようになっている。 ニフティのpppとは、筆者がノートパソコン+PHSでアクセスしたときの「it bs〜.ppp.infoweb.ne.jp」を許可するようにした。 もちろん、このあたりは、読者の環境に合わせて変えてほしい。 条件を満たさなかったユーザーには、「テスト成功!無事表示された。1998年1 月5日」と、ダミーの表示を見せている。
「あなたには秘密のページは見せられません」などと表示して、万一、このページを 偶然表示してしまったユーザーを煽らないようにしたい。旧い日付で、「テスト成功」 と書かれていれば、それ以上の興味はもたないだろう。 パスワードが表示されたら、スクリプトの最初で設定している「123」を入力する 。
パスワードに間違った場合も、「テスト成功」の表示をしている。
パスワードのチェックをクリアすると、「秘密の掲示板へようこそ」が表示される。 実際に掲示板のプログラムを組むとすれば、この行から始めれば良いわけだ。
以上は、ローカルLANからチェックを行なったが、いよいよ、外のネットワークか らアクセスしてみよう。 モデムの管理画面から、「取得 WAN側IPアドレス」などに該当する欄を見つけ 、割り振られたグローバルIPをチェックする。今回は、「61.124.23.xx 」であったので、携帯に、「http://61.124.23.xx/cgi-bi n/s.pl」と入力する。
見事!パスワード・チェックの画面になった。
* 今回の方法では、IPが変わると携帯からアクセスできなくなるが、最初の一歩はこ れで果たせた。あとは、変わったIPをどのように知るかという手法により、携帯から も自由に自宅のデータを触れるようになる。 そのような、めまいを禁じ得ない楽園を、少しずつ読者と共有していきたい。どうか 、この連載を固く信じ、最後までついてきてほしい。 HP「今日からCGIプログラマー(http://www.geocities.c o.jp/SiliconValley-Cupertino/6103/)」 (辻 豊史) リスト1 限定公開コンテンツの実験(s.pl) #!C:/Perl/bin/MSWin32-x86-object/jperl #このスクリプトは、s-jisで保存すること。Jperl用のスクリプトである #---リモートアドレスからリモートホストを得る $rht = gethostbyaddr(pack("C4", split(/\./,$ENV{'REMOTE_ADDR'})), 2); $password = "123";&getqs;$ok = 0; @u_agent = split(/\//,$ENV{'HTTP_USER_AGENT'}); #---ユーザーエージェント(ブラウザ)チェック ($u_agent[0] eq 'J-PHONE') && ($ok = 1); ($u_agent[0] eq 'Mozilla') && ($ok = 1); #---リモートホストが条件を満たし、$u_agentがMozillaだと$ok=2になる ($rht =~ /.*skyweb\.jp-t\.ne\.jp/) && ($ok++); ($rht =~ /itbs.*\.ppp\.infoweb\.ne\.jp/) && ($ok++); #---ローカルからのアクセスなら、無条件に$ok=2 ($ENV{'REMOTE_ADDR'} =~ /^192\.168\..*/) && ($ok=2); #---条件を満たした時のみ、本当のページタイトル表示 $title = "test";($ok == 2) && ($title = "秘密の掲示板"); #---ヘッダ表示 print "Content-type: text/html\n\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"><HTML><HEAD><TITLE>$title</TITLE> <META http-equiv=Content-Type content=\"text/html; charset=Shift_JIS\"></HEAD><BODY>"; #---条件に合わないユーザーにはダミー表示 if ($ok != 2) { print "テスト成功!無事表示された。1998年1月5日 </BODY></HTML>";exit(0);} #---パスワードなしの場合、パスワードを要求して終わり if ($qs{'PS'} eq ""){ print "<FORM action=\"$ENV{'SCRIPT_NAME'}\" METHOD=\"GET\"> ?<input name=\"PS\"><br><INPUT TYPE=\"submit\" name=\"send\" VALUE=\"送信\"></BODY></HTML>"; exit(0);} #---パスワードが違っていた場合、ダミー表示 if ($password ne $qs{'PS'}){ print "オッケー!テスト成功!</BODY></HTML>";exit(0);} #---実際の処理 print "秘密の掲示板へようこそ"; print "<BR>こっから先はできてませんが……"; print "<BR>ユーザーエージェント=$u_agent[0]"; print "<BR>リモートホスト=$rht"; print "<BR>リモートアドレス=$ENV{'REMOTE_ADDR'}</BODY></HTML>"; exit(0); #---query string解釈(サブルーチン) sub getqs {@get = split(/&/, $ENV{'QUERY_STRING'}); foreach (@get) { ($x ,$y) = split(/=/, $_);$qs{"$x"} = $y;} }