みなさん、こんにちは!フリューでモバイルサイト開発を行っている鷲見といいます。
現在Amazon Web Services 1ヶ月導入記という記事を書いているのですが、今回はAWSを導入したことで経験した少し困ったことを記事にしてみました。
今までは某データセンターにサーバを置いていたため、設定でHTTPプロキシを介さずにデータのやり取りを行っていました。しかし、今回導入したAWSのEC2では、HTTPプロキシを介してのやりとりを行う必要がありました。
フリューではプログラムのデプロイや各種ミドルウェアの再起動にApache Antを利用しています。ここで困ったのがAntのSCP/SSHEXECのタスクにはHTTPプロキシを設定できないということでした。
AntのFTPタスクではプロキシを設定することができるのですが、SCP/SSHEXECタスクでは設定できません。何故こうなってるのかはよくわかりませんが、最新のAntのソースコードまで読んだので間違いありません。
ただし、Antが内部的にSCP/SSHEXECで利用しているJSchにはプロキシを設定する箇所があります。
これはAntかJSchどちらかのソースコードを改造すれば対応できそうです。というこで今回はAntとJSchの両方での修正について紹介したいとおもいます。
JSchとは?
JSchはJavaでSSH2のクライアント側が実装されたライブラリで、Ant、Eclipse、Netbeansなどでも利用されています。ちなみに作者は株式会社ジェイクラフトの山中淳彦さんという日本の方です。
ライセンスは修正BSDライセンスとなります。
タイトルから分かるようにJSchというのはJava Secure Channelの略語のようです。
Antのコードを修正してみる
JSchではプロキシの設定はSessionクラスにProxyクラスをセットして行っています。
ということはAntのコードの中でJSchのSessionクラスの利用箇所を探して、Proxyクラスをセットするようにすればよさそうです。
ちなみに今回修正しているAntのバージョンは1.7.1です。
http://archive.apache.org/dist/ant/source/apache-ant-1.7.1-src.zip
調査したところ、org.apache.tools.ant.taskdefs.optional.ssh.SSHBaseというクラスのopenSessionというメソッドでSessionをJSch側から取得しています。どうやらこのopenSessionメソッドを修正すればよさそうです。というわけで早速修正してみました。
org.apache.tools.ant.taskdefs.optional.ssh.SSHBase.java
//追加箇所ここから import com.jcraft.jsch.Proxy; import com.jcraft.jsch.ProxyHTTP; //追加箇所ここまで … protected Session openSession() throws JSchException { JSch jsch = new JSch(); if (null != userInfo.getKeyfile()) { jsch.addIdentity(userInfo.getKeyfile()); } if (!userInfo.getTrust() && knownHosts != null) { log("Using known hosts: " + knownHosts, Project.MSG_DEBUG); jsch.setKnownHosts(knownHosts); } Session session = jsch.getSession(userInfo.getName(), host, port); //追加箇所ここから Proxy proxy = new ProxyHTTP("HTTPプロキシサーバのIPアドレス:ポート番号"); session.setProxy(proxy); //追加箇所ここまで session.setUserInfo(userInfo); log("Connecting to " + host + ":" + port); session.connect(); return session; }
上のプログラムの『“HTTPプロキシサーバのIPアドレス:ポート番号”』の箇所は自分の環境にあわせてください。例えばサーバが192.168.10.1、ポートが3333の場合は『“192.168.10.1:3333”』となります。
HTTPプロキシサーバのIPアドレス・ポート番号が変更になる可能性がある場合はこの設定をファイルや環境変数にした方が良いかもしれません。
修正が完了したら、antのソースコードを解凍した直下にあるbuild.xmlのdistターゲットをAntで実行すれば、修正されたjarが
{Antの解凍ディレクトリ}/build/lib/ant.jar
に作成されます。
現在利用されているant.jarを、修正したant.jarに置き換えることでHTTPプロキシを超えてSCP/SSHEXECを利用することができるようになります。
JSchのコードを修正してみる
JSchはプロキシ設定をする箇所があり、Antがプロキシ設定をしていないだけなので、本来的にはAntを修正すべきなのですが、Antを修正するとあとでいろいろと影響が出そうで嫌だという場合にはJSch側を修正してみます。
ちなみに今回修正しているJSchのバージョンは0.1.44です。
http://sourceforge.net/projects/jsch/files/jsch/0.1.44/jsch-0.1.44.zip/download
Antの修正時に呼び出しているJSchクラスのgetSessionメソッドでSessionクラスのインスタンスを生成しているようなので、このメソッドを修正してみましょう。
com.jcraft.jsch.JSch.java
public Session getSession(String username, String host, int port) throws JSchException { if(username==null){ throw new JSchException("username must not be null."); } if(host==null){ throw new JSchException("host must not be null."); } Session s=new Session(this); s.setUserName(username); s.setHost(host); s.setPort(port); //追加箇所ここから Proxy proxy = new ProxyHTTP("HTTPプロキシサーバのIPアドレス:ポート番号"); s.setProxy(proxy); //追加箇所ここまで //pool.addElement(s); return s; }
上のプログラムの『“HTTPプロキシサーバのIPアドレス:ポート番号”』の箇所は自分の環境にあわせてください。例えばHTTPプロキシサーバが192.168.10.1、ポートが3333の場合は『“192.168.10.1:3333”』となります。
修正が完了したら、JSchのソースコードを解凍した直下にあるbuild.xmlのdistターゲットをAntで実行すれば、修正されたjarが
{JSchの解凍ディレクトリ}/dist/lib/jsch-yyyymmdd.jar
に作成されます。(yyyymmddはbuildを行った日付です。)
現在利用されているant-jsch.jarを、修正したjsch-yyyymmdd.jarに置き換えることでHTTPプロキシを超えてSCP/SSHEXECを利用することができるようになります。
まとめ
この記事ではAntでHTTPプロキシ経由でSCP/SSHEXECタスクを実行するため以下のようなことを行いました。
- Ant側のJSchのSessionクラスの利用箇所でプロキシ設定の追加
- JSch側のSessionクラスのインスタンス生成箇所でプロキシ設定の追加
Antを修正するか、JSchを修正するか。プロキシ設定を直書きにするか、ファイルにするか、環境変数にするかはみなさんの判断にお任せしたいと思います。
今回は少しAWSから離れて、AWS導入で困ったことの解決方法を記事にしてみました。AWSに関する記事も鋭意製作中ですのでしばらくお待ちくださいませ。