ssh を任意のポート、プロトコルの proxy にする

[2005-11-17] SSH 経由でネットワーク共有フォルダにアクセスする」の応用すると、次のような事例についても応用できる。
– Firewall があって ○○○ が使えないけど無理に使いたい
– クライアントからの○○の送信, アクセス元 IP アドレスをサーバの IP アドレスにしたい(例.メール送信元の隠蔽)
 
仕事で VNC 接続をサーバからにする必要があり、応用してみた(VNC over SSH using PuTTY)。
– Loopback NIC の IP アドレス(ex. 169.254.0.2)についてポート番号 5900 (VNC のディスプレイ0 のポート)への接続が ssh サーバ(ex. ssh.example.org)経由での接続先ホスト(ex. target.OCexample.com)の5900番への接続になるようにローカルポートフォワードする。こんなかんじ。

ssh -N -L 169.254.0.2:5900:target.example.com:5900 ssh.example.org

 -Nは接続後にシェルを開かないためのオプション。通常通り端末操作を行いたい場合ははずしてもよい。
PuTTY でやるなら、SSH トンネルのポートフォワーディングで
 
– 源ポート: 169.254.0.2:5900
– 送り先: target.example.com:5900
– ローカル
 
として追加しておき、ssh.example.org に接続すればよい。
ローカルで 5900 を LISTEN していなければ、Loopback IP アドレスを使う必要はないため、この場合 PuTTY では源ポートの指定はポート番号のみでよい。また ssh コマンドでは

ssh -N -L 5900:target.example.com:5900 ssh.example.org

でよい。
また、-g オプションと組み合わせて使うと、ローカルだけでなく外にもポートを開き、公開プロキシのように振舞えるようになります。

ssh -N -g -L 5900:target.example.com:5900 ssh.example.org

 
ダイナミックポートフォワーディングとローカルポートフォワーディングの
メリット、デメリットは次の通り。
 
– ダイナミック
○ 一度の設定で、サーバからアクセスできる場所であればどこにでもアクセスできる。
× SOCKS サーバとして動作するため, プロキシ接続用のクライアントソフトが SOCKS プロトコルに対応している必要がある。
 
– ローカル
○ SOCKS プロトコルに対応している必要がなく、どんなクライアントソフトでも利用できる。
× 接続先、ポート番号を逐一マッピングする必要があるため、複数箇所に対しては手間。

SSH 経由でネットワーク共有フォルダにアクセスする

SMB over SSH
 
要するに, Microsoft Loopback Adapter ドライバをいれ、そこに実際の LAN とは別のネットマスクの LAN IPアドレスを振り、そのアダプタについてポート 139 番の LISTEN をなくした上で、その IP の 139 ポートに対しての接続を全てサーバ側 LAN の指定ポートにローカルフォワードすればよい。詳細はリンク先にあります。

DoJa エミュレータでオプションとなっている API を使うと例外が出る

少し前にはまった。DoJa エミュレータのデフォルトではライブラリが不足しているので呼び出そうとすると RuntimeError になる。エミュレータ上で正しく動作させるには micro3d_v2_32.dll というファイルを DoJa の bin フォルダにいれてやる必要がある。
<http://www.mascotcapsule.com/toolkit/docomo/>
– micro3d_v2_32.dll の配布元。
– 追記 2005-12-19: ダウンロード場所がわかりにくい気がするので捕捉。現在、
DoJa 2.5oe/3.0/3.5 の Tools -> DLL micro3d_v32.dll でダウンロード可能。

ブラウザでページを操作

– ブラウザのアドレスバーを使った遊び。日本語テキストたっぷりなページでを開いた後、次のコードをアドレスバーにいれて実行すると文章を書き換える。

javascript:varelm=document.getElementsByTagName(“body”)[0];elm.innerHTML=elm.innerHTML.replace(newRegExp(“。”,”g”),”にゃ。”);

堅苦しい言葉がトロ語に。replace 使うと Firefox だと化けるなぁ.. split(“from”).join(“to”); としたほうがいいかも。

document.getElementsByTagName(“body”)[0].innerHTML;

これがキモ。DOM メソッドを使って Body タグの全文章を取得/操作する。

追記[2005-06-22]:

document.getElementsByTagName(“body”)[0]

は、

document.body

でも参照可能らしい。某所にあったコードのほうが汎用的で簡素みたい。

JavaScript:document.body.innerHTML=document.body.innerHTML.split(‘。’).join(‘にゃ。’);focus();

focus() しないと、実行後が別ページ扱いになって相対パスの外部ファイル(画像, js, css)の読み込みに失敗して見ためが崩れるみたい。

JDBC のログとりメモ

– close() するのは PreparedStatement#close() でなく ResultSet#close() でもなく、絶対に Connection でなければならない。
– ログ情報には PreparedStatement#toString() がよさげ(少なくとも com.mysql.jdbc では)。
理由は、ログのための利便性から。SQLException がどのクエリでエラーになったかを残してくれないので、 PreparedStatement インスタンスがクエリ周りの情報をきっちり保持してくれていれば、toString() でログにどのクエリ文を実行したかが残せる。しかし、PreparedStatement#close() は DB 接続を閉じる仕様とは限らないため、Connection#close() を呼ぶ必要がある。PreparedStatement#close() だけにしたらプールがあふれ、思わぬ場所で DB 接続が開くのをずっと待ち続けることになってしまった。
– 例:

boolean isExist(int id){
    PreparedStatement ps = null;
    try{
        final Connection con = getConnection();
        try{
            ps = con.prepareStatement(“SELECT id FROM list WHERE id = ? LIMIT 1”);
            ps.setInt(1, id);
            return ps.executeQuery().next();
        }finally{
            con.close();
        }
    }catch(SQLException e){
        log(“Query error [“+ps+”]”, e); // void log(String, Throwable); とする
        return false;
    }
}

Servlet の基本

– 基本は通常のクラスと同じだが、条件として javax.servlet.http.HttpServletを親クラスとする必要がある。
– protected void do*(HttpServletRequest, HttpServletResponse)
doGet, doPost, doDelete, doHead, doOptions, doPut, doTrace があり、それぞれ対応するリクエストのときに呼び出される。
– protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException
別のオーバーロードされた service メソッドから処理を受け、配分するのが役目なので protected。
parent.service(req,res) を呼び出した時点で do*(req,res) の処理が行われるので、その前後の共通動作を定義するのに便利。
– 日本語(マルチバイト文字)を引数にとる
— getParametervalues,getParameterを使い、化けた状態の文字を取得したあと

new String(string.getBytes(“ISO_8859_1”), “Shift_JIS”);

のようにする。(HTTPプロトコルの文字コードが ISO-8859-1 のため)
— HttpServletRequestクラスのsetCharacterEncodingで、パラメータを取得する前にエンコードを指定しておく。
— HttpServletRequest#setCharacterEncoding(String enc) の挙動の違いの問題に注意!
Tomcat 4.1.29 以降の 4.1.*/5.0.16以降の 5.0.*、では、Getメソッドではエンコードされなくなった。GETの引数はURIに含まれるので、URIはエンコードされるべきではないという見解による仕様変更とのこと。
– スレッドセーフということ。
サーバサイドでは1つのインスタンスを使いまわしてマルチスレッドで動作するので、スレッド同士の不要な干渉をなくさなければならない。
“staticではない”フィールド(インスタンス変数)もスレッド間では共有されている事に注意!
–> ページ閲覧者固有の変数を持ちたい場合、メソッド内で定義した変数を使わなければならない。
データアクセスなど同期を取らないといけない場合は、(デッドロックにくれぐれも注意しつつ)適宜 synchronized にする。

メールのContent-Header, Content-Body の仕様(RFCのピックアップまとめ)

世界中で標準となっているeメール仕様(SMTPプロトコル仕様)はRFC822などのRFCドキュメントです。
原本を読めばすべて書かれているのですが、全部読むのは大変なのでピックアップしてまとめてみました。

続きを読む メールのContent-Header, Content-Body の仕様(RFCのピックアップまとめ)

[JavaScript][ActionScript] ブロック({ … }) ではスコープの限定ができない

一時変数のスコープを絞るのに { … } をよく使うが、ECMAScript (ActionScript/JavaScript 共通) だと物理的には意味をなさなくなる。例えば、次の文はエラーにはならない:

{var t=”NG”;} alert(t);

ブロックがスコープを持つなら、t は alert() を呼ぶ時点では存在しないためエラーになるべきだが、実際は NG と表示されてしまう。(Firefox 1.0, IE6, Flash MX 2004 で確認)
 
これは制御構文でも同じで、例えば、

for(var i; i < 10; i++){ var n = i; }

は、for 文の終了後に

i = 10; n = 9;

が入ったままになる。スコープを切りたい場合は、その部分だけ関数を使う等するしかなさそう。個人的に、リファクタリングの準備のために頻繁にスコープを切るのでこれは不便だなぁ..
ECMAScript では関数スコープであることを宣言するときのみ var 宣言は意味を成しているよう。
 

簡易タイマー

例えば 1 分後にアラートを鳴らすには次のようにすればよい。
– Windows なら sleep というコマンドを使えるようにしてコマンドプロンプトで

sleep 60 && echo <Ctrl-G>

  • UNIX 系(bash, sh)なら

sleep 60 && printf “\a”

 
追記:
(2006-05-10) sleep が Windows 標準で存在しないことに気づき訂正.