内部のPHPスクリプトから外部のAPIサーバへ、メインIPではない公開しても良いサブIPアドレス(複数)をアクセス元としてHTTPリクエストを送る方法があれば教えて下さい。
可能であれば動的に割り当てられたグローバルIPを自由に選択して外部にアクセスが出来ると理想です。
言い換えると、発信元のIPアドレスをLinux上の何らかのコマンドでサーバを稼働させたまま動的に変更する事は出来ますでしょうか。
※ ListenさせるIP毎にproxyサーバを建てる方法は避けたいです
こんな感じでしょうか?
<?php function my_http_get($host, $path='/', $source_ip='0.0.0.0') { // 新しいソケットを作成する $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); // ソースアドレスをバインドする socket_bind($sock, $source_ip); // 接続先ホストと接続する socket_connect($sock, gethostbyname($host), 80); // リクエストを書き込む $request = "GET {$path} HTTP/1.0\r\n" ."Host: {$host}\r\n" ."\r\n"; socket_write($sock, $request); // レスポンスを取得 $response = ''; while(1) { $buf = socket_read($sock, '1024'); if($buf === '') { break; } $response .= $buf; } // ソケットを閉じる socket_close($sock); // HTTPレスポンスからヘッダ部分を削除 $content = preg_replace('/^.*?\r\n\r\n/sm', '', $response); return $content; } //接続元IPを指定してGET (a.b.c.dは自分のIP) echo my_http_get('www.yahoo.co.jp', '/', 'a.b.c.d'); ?>
ソケットを直接扱えば接続元IPの指定が出来ます。
ただしその場合はHTTPリクエストを作ったりレスポンスからコンテンツを分離する作業なども自分でやる必要もあります。
上記は a.b.c.d を帰れば一応動くと思いますが、エラー処理などは全くしてないので実際に使うにはもう少しキチンと書く必要があると思います。
複数個のグローバルIP
これらはネットワーク的には同一サブネットに属しますか?
同一サブネットでなければ route コマンドでルーティング情報を制御することにより、
特定の相手先への経路を変更することが出来ます。
可能であれば動的に割り当てられたグローバルIPを自由に選択して外部にアクセスが出来ると理想です。
動的に、というところがちょっとやっかいですが、iproute2 を使えばおおよそ希望した動作が得られるかと。
NETMARKとiproute2でトラフィックを完全掌握 − @IT
こういった動作は業務用ルーターではさして珍しくない機能として持っていることが多いですが、
Windows/Linux などの汎用のOSではほとんど有りません。
紹介頂きありがとうございます。
LIDSを組み合わせると出来そうなのですが、デーモンではなくphpという小さなスクリプトなため、コントロール対象とするのは難しそうです。
こんな感じでしょうか?
<?php function my_http_get($host, $path='/', $source_ip='0.0.0.0') { // 新しいソケットを作成する $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); // ソースアドレスをバインドする socket_bind($sock, $source_ip); // 接続先ホストと接続する socket_connect($sock, gethostbyname($host), 80); // リクエストを書き込む $request = "GET {$path} HTTP/1.0\r\n" ."Host: {$host}\r\n" ."\r\n"; socket_write($sock, $request); // レスポンスを取得 $response = ''; while(1) { $buf = socket_read($sock, '1024'); if($buf === '') { break; } $response .= $buf; } // ソケットを閉じる socket_close($sock); // HTTPレスポンスからヘッダ部分を削除 $content = preg_replace('/^.*?\r\n\r\n/sm', '', $response); return $content; } //接続元IPを指定してGET (a.b.c.dは自分のIP) echo my_http_get('www.yahoo.co.jp', '/', 'a.b.c.d'); ?>
ソケットを直接扱えば接続元IPの指定が出来ます。
ただしその場合はHTTPリクエストを作ったりレスポンスからコンテンツを分離する作業なども自分でやる必要もあります。
上記は a.b.c.d を帰れば一応動くと思いますが、エラー処理などは全くしてないので実際に使うにはもう少しキチンと書く必要があると思います。
求める動作が行われる事を確認しました。ありがとうございます。素晴らしいです!!
実際に使う場合、例えばどのようなエラー処理をする必要があるか、箇条書きでもかまわないので頂けると幸いです。
404, 500などのエラー処理やLocationヘッダが返ってくる事の他に、何か対応が必要そうな物はありますでしょうか?
404や500などのHTTPステータス毎の処理もそうですが、それとは別にsocket通信そのもののエラー処理もちゃんとした方がよいです。
エラー処理の典型的なやりかた等はPHPのマニュアルのサンプルやネット上の情報が色々あるのでsocket関係の関数名をキーワードに探せば色々見つかると思います。
ありがとうございます!
求める動作が行われる事を確認しました。ありがとうございます。素晴らしいです!!
実際に使う場合、例えばどのようなエラー処理をする必要があるか、箇条書きでもかまわないので頂けると幸いです。
404, 500などのエラー処理やLocationヘッダが返ってくる事の他に、何か対応が必要そうな物はありますでしょうか?