[telnetでWeb siteを見る]で述べたように、telnetクライアントはHTTPクライアントとしても使えます。この時、実はHTTPプロクシを使ってWeb siteにアクセスする事ができます。
方法はというと、まずtelnetクライアントでプロクシサーバーに接続します。それからGET等のメソッドで取得するファイルを正確な絶対URIで指定すれば、プロクシを通してデータが送られてきます。
以下に例を示します。ここでは仮にproxy.anony.com(ポート8080)というプロクシを使って、Yahoo! Japanのトップページを取得します。
まずプロクシに接続します。
C:\>telnet proxy.anony.com 8080
接続できたら、GETメソッドでhttp://www.yahoo.co.jp/index.htmlを取得します。
GET http://www.yahoo.co.jp/index.html HTTP/1.1
Host:www.yahoo.co.jp
[telnetでファイルを転送する]で述べたように、telnetクライアントはFTPクライアントとしても使えますが、この時、Squid等のFTP over HTTP proxyをサポートしたHTTPプロクシを使ってFTPサーバーにアクセスする事ができます。
動作の概念は、ローカルからプロクシへのHTTPリクエストを、プロクシが対応するFTPに翻訳してFTPサーバーと通信を行い、その結果をHTTPを使ってローカルに返します。つまり、ローカル・プロクシ間をHTTP、プロクシ・FTPサーバー間をFTPを使って通信するということです。
以下にSquidにおける両プロトコルの対応を示します。各コマンド等の意味については、それぞれの解説ページを参照してください。
HTTPメソッド | FTPコマンド |
---|---|
PUT | STOR(, MKD) |
GET | RETR |
ディレクトリの作成は、PUTメソッドの引数(絶対パス)に存在しないディレクトリが含まれる場合、自動的にSquidがMKDすることで行われます。DELE/RMDコマンドに相当するメソッドにはDELETEがありますが、この対応は現在のところ実装されていません。
パスの指定には絶対URIを用いますが、この時スキームを"ftp"として、"ftp://servername/path"のようにします。FTPサーバーの認証は、HTTPアクセス認証を使うか、あるいはURIにユーザー名、パスワードを含めて送信します。URIにユーザー名等を含める場合は、以下のようになります。
METHOD ftp://username:password@servername/path HTTP/1.1
また、HTTPアクセス認証を使う場合で、基本認証の場合は以下のようになります。
METHOD ftp://servername/path HTTP/1.1
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
AuthorizationヘッダフィールドのBasicの後の文字列は、ユーザー名とパスワードを":"(コロン)で区切ったものをbase64エンコードしたものです。ここでは"username:password"をエンコードしたものになります。ダイジェスト認証の場合については割愛します。
通信の手順は、まずtelnetクライアントでプロクシサーバーに接続します。それからダウンロードであればGETメソッドで取得するファイルを正確な絶対URIで指定すれば、プロクシを通してデータが送られてきます。アップロードであれば、PUTメソッドになります。
以下に例を示します。ここでは仮にproxy.anony.com(ポート8080)というプロクシを使って、このサイトのトップページを取得します。FTPサーバーのユーザー名、パスワードはそれぞれuser、passであるとします。
まずプロクシに接続します。
C:\>telnet proxy.anony.com 8080
接続できたら、GETメソッドでftp://www.nurs.or.jp/home/telnet/public_html/index.htmlを取得します。
GET ftp://user:pass@www.nurs.or.jp/home/telnet/public_html/index.html HTTP/1.1 Host:www.nurs.or.jp HTTP/1.1 200 OK Connection: close Last-Modified: Sun, 16 Jan 2005 12:30:53 GMT Content-Type: text/html Via: Version 1.0 release-Build 1348-10/28/2003(IWSS) Age: 0 〜以下ファイルの内容〜
パスにディレクトリが指定されると、ディレクトリ内のファイル名とその更新日時等のインデックスが取得できます(HTMLで記述されています)。
次にpublic_htmlディレクトリにファイルtext.txtをアップロードしてみます。PUTメソッドにはアップロードする内容の正確なサイズ(オクテット数)が必要なので、Content-Lengthを使って示します。ここでは200オクテットのデータをアップロードします。
GET ftp://user:pass@www.nurs.or.jp/home/telnet/public_html/index.html HTTP/1.1 Host:www.nurs.or.jp Content-Length: 200 〜ファイルの内容〜 HTTP/1.1 200 OK Proxy-Connection: Keep-Alive Connection: Keep-Alive Content-Type: text/plain Content-Length: 24 226 Transfer complete.
Netscape等のブラウザがHTTPプロクシを使ってFTPサーバーにアクセスしている時、内部ではこのようなやりとりが行われているのです。このFTP over HTTP proxyが可能なFTPクライアントはほとんどありませんが、lftpはサポートしているようです。
通常、サーバーホストは色々なネットワークサービスを提供しており、それらサービスを提供するためのサーバープログラムがサーバー上では動いています。これらのプログラムは各サービス毎にポートを占有し、例えばHTTPなら80番、FTPなら21番、といった具合に、それぞれのサービスが占有するポート番号はある程度決まっています(これをWell-known Portと呼びます)。
従って、有効な(開いている)ポートの番号を調べる事で、サーバー上で動いているプログラムを知る事ができます。
既に述べたように、telnetクライアントは接続するポートを指定できます。指定されたポートが開いていれば接続でき、閉じていたら接続できません。つまり適当なポートを指定して接続を試み、(TCP)コネクションが確立できれば、そのポートは開いているという事になります。
では実際にtelnetクライアントを使って、ポートスキャンをしてみましょう。次のようにDOSプロンプトや「ファイル名を指定して実行」等に入力して接続します。ポート7はechoです。
C:\>telnet www.yahoo.com 7
「接続できない」といった感じのメッセージが出れば、www.yahoo.comではポート7は閉じている、つまりechoサービスは行われていないという事になります。
指定するポート番号だけ変えてこれを繰り返せば、そのサーバーのポートの状態を調べる事ができます。
ただし、ポートスキャン自体は犯罪ではありませんが、不正アクセスの下準備として行われる事が多いので、サーバー管理者に知られるといい顔はされません(というか明らかに嫌がられる)ので、あまりやらないように。不正アクセス禁止法がどの程度の行為まで適用されるのかは解りませんが、もしやる時は自己責任でお願いします。
Webサイトにアクセスしてきた相手のIP(アドレス)を知るには、CGIの環境変数を使って取得する方法が一般的です。しかしこれは、接続元IPを漏らさないプロクシを使う事で、本当のIPが知られる事を防ぐ事が可能です。また、プロクシサーバー特有の環境変数を全く吐かない、いわゆる匿名串を使えばプロクシを使っている事すら判らなくなりますので、本当のIPの取得は更に困難になります。
また、有名なIP抜きの方法としてJAVA Appletを使ったものがあります。JAVAのSocketをApplet内で生成して、プロクシを経由させないで直接CGIにアクセスさせたりすると、直接コネクションを張るわけですから、生IPを抜く事ができます。ただしこれも、ブラウザの設定でAppletを起動させないようにしておくことで、簡単に防がれてしまいます。
他の有効な――普通の状態では防げない(JAVAオフは普通です)――方法の一つに、ここで扱う他プロトコルを使ったものがあります。
Internet ExplorerやNetscape Navigator、Netscape Communicatorといったブラウザは、HTTPやHTTPS以外の様々なプロトコルをサポートしています。ブラウザの設定を開いてみると、Secure、FTP、Gopher、Socksといったプロトコルに、プロクシを設定できる(つまりこれらのプロトコルをサポートしている)事が判ります。
最初に述べた「他プロトコル」とは、これらプロクシを設定できるプロトコル以外の、ブラウザがサポートしているプロトコルの事です。それらのプロトコルで接続する時は当然直接アクセスする事になりますので、それを利用して生IPを抜くわけです。
具体的にどうするのかというと、ダミーサーバーを動かし、フレームタグを使ってtelnetプロトコル等でそのダミーサーバーにアクセスさせます。Cr[y]ackerzのhimikoさんが実装(ipget.c)した事で有名です。
と、言う訳で、サンプルスクリプトを置いておきます。期待を外して申し訳ないのですが、これはhimiko氏ではなく私が適当に作ったものです。サーバー部分は68user's pageのechoサーバーを流用させて頂きました。ダミーサーバーは、プロトコルに準拠していなくても、サーバー機能を有してさえいればいいようですので。
telnetが起動してクライアントにメッセージが表示されれば成功です。ただし成功してもブラウザ側に何も表示されない事もあるので、その時はリロードしてみて下さい。「接続できない」というメッセージが表示されたら、リロードしてみて下さい。あと、あまり遅いプロクシを使っていると、ダミーサーバーに上手く接続できずにタイムアウトになってしまうかもしれません。
動作を確認したブラウザは、Internet Explorer 5.01以降、Netscape 6、Opera 6.01(for Win)以降、Konqueror(いずれも初期設定のまま)。そのうち期待した動作を示したのは、Internet Explorer、Operaのみです。
相手の生IPを抜くだけの最小機能版のソースを公開します。ただし、私はPerlをきちんと学んだことはないので、機能と動作は保証の限りではありませんが。不具合があれば報告して下さると嬉しいです。
[telnetでファイルを転送する]で述べたように、FTPは二種類のコネクションを使用します。普通はどちらのコネクションもサーバーとユーザーの間に張りますが、実はサーバーがデータコネクションを張る相手はユーザーである必要はありません。別のサーバーとデータコネクションを張っても構わないのです。
具体的にはユーザーが二つのサーバーとコントロールコネクションを張り、二つのサーバーをデータコネクションで結びます。これによってユーザーは二つのサーバーを同時に制御することができ、データを両サーバー間のデータコネクションを通して一方からもう一方へと直接転送することができます。
既に訳が解らなくなっている方もいるかと思いますから、図を入れておきます(RFC 959より抜粋)。
Control Connection +----------+ Control Connection +--------->| USER |<---------+ | +----------+ | V V +------------+ Data Connection +------------+ | Server A |<-------------------->| Server B | +------------+ +------------+
これができると何が嬉しいのかと言うと、普通、あるサーバーから別のサーバーにファイルを送りたい時は、一度ローカルを挟むというのが一般的なやり方です。つまり ダウンロード→アップロード のツーアクションで転送するわけですね。しかし、FTPではわざわざこのようなことをしなくても、サーバー間で直接ファイルをやりとりすることができるのだ、ということです。
では実際にはどのようにしてサーバー間転送を行うのか、以下に示します。ここでは、やや紛らわしいのですが、GeocitiesからGeocitiesへ(ジオの中でサイト移転をすると考えて下さい)ファイルを送りたいと思います。
telnetを二つ起動させ、転送先・転送元の両方のFTPサーバーにそれぞれ接続します。ポート番号は21です。接続できたら次のようにします。番号の付いた行が入力するコマンド、他はサーバーからのメッセージです。コマンドの前の番号は、コマンド発行の順番を表すために付加したもので、実際には表示されません。転送元サーバーを"サーバーA"、転送先サーバーを"サーバーB"とします。
続けて他のファイルを転送する場合は上記の操作を繰り返します。その時気を付けるのは、繰り返すのは(5)〜(10)だということです。理由については[telnetでファイルを転送する]の章を参照して下さい。
なお(9)と(10)の発行先を逆にすれば、サーバーBからAへとデータが送られます。
それと、何故例で使用したサーバーを、両方ジオにするなどという紛らわしい真似をしたかと言いますと、このように外部へのデータ転送を許可しているサーバーが少なく、その様なサーバーを私があまり知らないからです。少なくともトクトクやf2sといったフリーウェブスペースを提供しているサーバーは、アクティブモード時、PORTで渡せるのはコントロールコネクションの相手だけのようです。パッシブモード時はファイルを転送しようとすると応答が無くなってしまいました。もしかすると凄まじく遅いだけだったのかもしれませんが、仮にそうだったとしても、実用に耐え得るスピードではないので、同じことです。
このサーバー間転送というのはあまり知られていませんが、仕様にも載っている方法です。RFC 959 "2.3.THE FTP MODEL"には、It should be noted that the data port need not be in the same host that initiates the FTP commands via the control connection
とありますし、"2.3.THE FTP MODEL"及び"5.2.CONNECTIONS"には、この転送法が載っています。つまりFTPはこうする(データをやり取りする二者を第三者が外から制御する)ことを予め想定して作られているのです。
このサーバー間転送を実装しているクライアントはそれほどありません。(実装した数少ないクライアントに、FlashFXP(Share)やSmartFTP(Free)等があります。)また特に、仕様上の機能であるにも関わらず、サーバーが禁止しているのは、FTP Bounce Attackと呼ばれる攻撃に利用されるのを防ぐためのようです。
FTP Bounceとは、FTPサーバーに別のサーバーに対してコネクションを張らせて攻撃を行う攻撃法で、ポートスキャンなどに利用されます。これによって、攻撃者はFTPサーバーを中継して対象ホストに攻撃を仕掛けることができます。FTP Bounceの詳細はFTP Bounceを参照。