sshのダイナミックポートフォワーディング(socksプロトコル)を使って、レンタルサーバをhttpプロキシにする(WEBページへのアクセス元IPアドレスを変える)

Wordpress

インターネット上のとあるWEBページにアクセスするにあたって、諸事情あってアクセス元IPアドレスを変えたかったのですが、家のAU光では簡単にはIPアドレスを変えられないので、別案件で使っているいくつか使っているレンタルサーバ(Linux)をプロキシサーバにできないか模索しました。

ただ、レンタルサーバなのであまり自由度がなく、sudoも実行できないのであまり手がありません。

いくつか方法を模索したところ、sshのダイナミックポートフォワーディング(socksプロトコル)を使うことで、レンタルサーバ側にはssh接続を有効にするだけで、httpプロキシにすることができたので、備忘録をかねて手順をまとめました。

アクセス元IPアドレスを変える方法

アクセス元IPアドレスを変えるには以下のような方法があります。

・レンタルサーバ側ではPHPのfile_get_contentsを使ってWEBページからデータを取って返す方法。
クエリストリングにアクセスしたいURLをつけてクライアントPCのブラウザからレンタルサーバにアクセスして、レンタルサーバ側のPHPがfile_get_contents()関数でWEBページにアクセスするという手法を試したところ、実現できました。しかし、クエリストリングでURLを送るため、文字数制限やurlエンコードがうまくいかず、いくつかのWEBページで正常にデータを取得できなかったため、他の方法を探しました。

・手持ちのスマホをテザリングする
これもクライアントPCにwifiがついていたのでスマホのテザリングを有効にして接続すれば実現できました。しかし、通信量が増えそうなことと、テザリングの有効無効の切り替えやwifiの切り替えも手間となるため、他の方法を探しました。

・sshのダイナミックポートフォワーディングを使う
通常sshというとクライアントPCからレンタルサーバにリモートでログインしてターミナルからコマンド操作できるようにするものですが、ダイナミックポートフォワーディングは同じ技術を使って全く別の機能を果たします。sshコマンドを実行する際、オプションで、ダイナミックポートフォワーディングであることを指定することで、レンタルサーバに対してダイナミックポートフォワーディング接続にします。接続すると、レンタルサーバがリクエストをWEBページに転送してくれるようになります。

ダイナミックポートフォワーディングがうれしいこと

・アクセス元IPアドレスを変えられる
・複数のレンタルサーバがあれば、アクセス元IPをころころ変えるようプログラミングできる
・複数のレンタルサーバが使えれば、負荷分散や同時アクセスも可能になる
・レンタルサーバ側に必要なのはsshのみ。格安サーバより上位であればたいがいのサーバはssh接続できる

sshのダイナミックポートフォワーディングの仕組み

元々、sshのポートフォワーディングには3種類あり、sshコマンドのオプション指定で、-Lによるポートフォワーディング、-Rによる逆ポートフォワーディング、-Dによるダイナミックフォワーディングを使うことができます。

今回は、-Dによるダイナミックフォワーディングを使います。

ダイナミックフォワーディングは、技術的にはsocksというプロキシ用プロトコルを使っています。なので、ブラウザのプロキシ設定やcurlのオプション指定でsocksの言葉が出てきますが、そういうものと思っていればOKです。

ダイナミックフォワーディング接続を行うと、クライアントPC側で「socksプロキシ」というプログラムが起動し、クライアントPC側のsocks用のTCPポート(コマンドオプションで指定する)にリクエストを投げると、ssh接続を経由してレンタルサーバに転送され、さらにレンタルサーバからWEBサーバにリクエストが転送されます。

その結果、WEBページから見たアクセス元IPアドレスは、レンタルサーバのIPアドレスになります。

レンタルサーバはクライアントPCからのリクエストを転送するので、プロキシとしての機能を果たしますが、squitなどのプロキシ用プログラムが起動しているのではなく、sshでsocksプロトコルを有効にすることで転送する動作をするようになります。

言葉がややこしいですが、クライアントPC側にもsocksプロキシというプロセスが起動して、クライアントPC側で自分自身にリクエストを投げ、socksプロキシがレンタルサーバに転送する動きをするので、クライアントPCとレンタルサーバが両方ともプロキシになって2段階の転送をするようになります。

また、クライアントPCをsocksプロキシとして利用できるのはクライアントPCだけです。他のPC上でsocksプロキシとして設定しても接続できません。

sshのダイナミックポートフォワーディングによるレンタルサーバhttpプロキシ化手順

それでは、具体的な手法を備忘録を兼ねて記載します。

環境

・クライアントPCのOSはLinux、Windowsで可能(接続時のローカルポートは10080番とする)(Linuxは標準のsshコマンドを使用。WindowsはフリーソフトのPuttyを使用)。
・httpプロキシにするレンタルサーバのOSはLinux

実現したい仕組み

クライアントPCのローカルポート10080番にアクセスすると、レンタルサーバ経由でインターネット上のWEBページにリクエストを投げ、レスポンスを取得する

作業の大きな流れ

1.レンタルサーバにsshで接続する手順を把握しておく
2.クライアントPCにてsshコマンドでレンタルサーバにダイナミックポートフォワーディング接続する
3.ブラウザやcurlにてsocksプロキシとしてローカルポート(2のコマンドで指定)を指定してWEBページにアクセスする
4.作業が終わったらダイナミックポートフォワーディングを解除する

1.レンタルサーバにsshで接続する手順を把握しておく

レンタルサーバがXサーバの場合は以下の手順です。
1.クライアントPCのホームフォルダの下に.sshフォルダを作る。

mkdir ~/.ssh

2.クライアントPCからXサーバのサーバパネルにアクセスし、SSH設定で秘密鍵と公開鍵を生成し、公開鍵をクライアントPCの~/.sshフォルダにダウンロードする。

3.公開鍵ファイルのパーミッションを600にする(パーミッションがデフォルト(604)のままだと、権限が緩すぎてエラーになる時がある)。

chmod 600 ~/.ssh/公開鍵ファイル名

4.一旦、以下のコマンドでレンタルサーバにSSH接続できることを確認する

ssh -l サーバパネルのログインユーザ名 -i ~/.ssh/公開鍵ファイル サーバのIPまたはDNS名 -p 10022

(sshの接続ポート番号は、Xサーバの場合は10022になります)

2.クライアントPCにてsshコマンドでレンタルサーバにダイナミックポートフォワーディング接続する

前述のsshコマンドにダイナミックポートフォワーディング接続用のオプションをつけてコマンドを実行する

ssh -l サーバパネルのログインユーザ名 -i ~/.ssh/公開鍵ファイル サーバのIPまたはDNS名 -p 10022 -N -f -D 10080

オプションの意味は以下。
-N:ssh接続先サーバではコマンドを実行しない(ダイナミックポートフォワーディングとしての転送しかしない)
-f:ssh接続をバックグラウンドで継続する
-D:ダイナミックポートフォワーディング接続であることを指定しつつ実際にアクセスするローカルポート番号を指定する
このコマンドを実行すると、プロンプトがすぐ返ってきますが、ps aux|grep sshなどで調べるとプロセスが残っていることが確認できます。

◆Windowsの場合
Windowsでは以下のアプリで可能です。
・Putty
・RLogin
・Teraterm
・Teraterm Pro + TTSSH
感覚的にはPuttyが簡単です。
Puttyであれば、設定メニューからConnection⇒SSH⇒Tunnelsを開く。
Dynamicにチェックを入れる。
SourcsPortに10080を入れてAddを押す。
Connection⇒SSH⇒Authを開いて「Private key file」に公開鍵ファイル(Puttyでは.key⇒.ppkに変換したファイルを指定する)を指定しておく。
Sessionから接続する

3.ブラウザやcurlにてsocksプロキシとしてローカルポート10080番を指定してWEBページにアクセスする

◆curlの場合
以下のどれでもできました。

curl --proxy socks5://localhost:10080 アクセスしたいWEBページのURL
curl --socks5 localhost:10080 アクセスしたいWEBページのURL
curl -X socks5://localhost:10080 アクセスしたいWEBページのURL

◆phpでプログラミングする場合
phpプログラムでアクセスしたい場合は、file_get_contents関数ではsocksプロキシに対応していないため使えないので、curl_exec関数を使います。
内部的にはcurl_setopt()関数でsocksプロキシを指定しておき、curl_exec関数でWEBページにアクセスします。
具体的なプログラムは以下です(簡単に使えるよう全体を関数化しています)。
curl_setopt()関数でのオプション指定によっては、正しくデータを取得できないWEBページもありますので、ここでは自分が試行錯誤した結果必要となったオプションを記載しています。
関数の第一引数$urlにWEBページのURLの文字列を指定すると、socksプロキシ経由でWEBページにアクセスして、html全体が文字列として返ってきます。
取得したhtmlは、loadHTML()関数で読み込んで$xpath->query()関数などで必要な部分を抽出・整形してもらえればOKです。

function curl_get_contents( $url, $timeout = 60 ){
	$proxy = 'socks5://localhost:10080';
	$user_agent = 'Mozilla/5.0 (Windows NT 5.1; rv:13.0) Gecko/20100101 Firefox/13.0.11';//それっぽい文字列であればOK
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $url );
	curl_setopt($ch, CURLOPT_HEADER, false );
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true );
	curl_setopt($ch, CURLOPT_TIMEOUT, $timeout );
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
	curl_setopt($ch, CURLOPT_PROXY, $proxy);
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
	curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
	$result = curl_exec( $ch );
	curl_close( $ch );
	return $result;
}

◆Windowsの場合(Puttyなどでダイナミックポートフォワーディング接続を実現している前提)
コントロールパネル⇒インターネットオプション⇒「接続」タブ⇒LANの設定⇒「LANにプロキシサーバーを使用する」にチェックを入れる⇒詳細設定⇒Socks欄にlocalhostとポート番号を入力すればOK。
そのあとは、chromeなりfirefoxなりedgeなりで普通にアクセスすれば、裏でsocksプロキシ経由でアクセスしてくれます。

4.作業が終わったらダイナミックポートフォワーディングを解除する

全て終わったら、クライアントPCでps aux|grep sshでバックグラウンドで実行しているsshコマンドを探してkillして下さい。

ssh関連プロセスがいくつか表示される場合は、自分が打ったコマンドのプロセスのみkillする。

ダイナミックポートフォワーディングを利用する際の注意点

1.レンタルサーバにssh接続できることが必要
2.レンタルサーバ複数ある場合は、1台のクライアントPCから複数のレンタルサーバに同時にダイナミックポートフォワーディング接続できる
3.複数のレンタルサーバに同時に接続する場合は、クライアントPC側のポートを別々にする
4.作業が終わったらsshプロセスをkillするのを忘れない

参考URL

ブレークスルーのきっかけになったページを紹介させていただきます。
sshによるポートフォワーディングまとめ
【PHP】cURLでYahooにログインする
エックスサーバーにssh接続する方法(ターミナル利用)
curlコマンドにてproxy設定
PHPメモ : file_get_contentsの代替にcURLを使う

Wordpress