2011/02/17

ssh

ssh (1) コマンドは接続先のホスト情報をローカルに保存していて、 接続するたびに接続先が正しいホストかを確認する機能を持っている。 これはホスト名の詐称や DNS poisoning などにより 正しくない接続先に接続してしまうという事態を防止するためには 非常に便利で有用な機能ではあるが、 接続先のシステムが再インストールなどでホスト情報が変更になってしまった場合、 ssh で接続しようとすると

$ ssh ホスト名
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX.
Please contact your system administrator.
Add correct host key in /home/ユーザ/.ssh/known_hosts to get rid of this message.
Offending key in /home/ユーザ/.ssh/known_hosts:NN
RSA host key for ホスト名 has changed and you have requested strict checking.
Host key verification failed.
$
    
などと表示されて接続できなくなってしまう。
画面に表示された通り known_hosts ファイルの該当行を削除すれば 再度接続できるのだが、 これを自動で行うためのスクリプトを作成してみた。

  1#!/bin/sh
  2cat << EOF | ex -s ${HOME}/.ssh/known_hosts
  3`ssh $* 2>&1 | sed -n '/^Offending key/s/.*:\(.*\)/\1/p' | tr -d '\r'`d
  4wq
  5EOF
    
PATH の通ったディレクトリに sshfix の様な名前で保存し 実行権限を付与しておくと、 ssh で接続を試みて上記エラーが発生した際に実行する事で known_host の該当行を削除するので再度接続できる様になる。

$ ssh ホスト名
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!</i>
   :
$ sshfix !$
$ ssh !$
        
くれぐれも本当に正しい接続先か確認してから利用しなければならない。

2011/02/12

シェルスクリプト自身のパス取得

シェルスクリプトを作成していて、 たまにスクリプト自身のパスを取得したい場合がある。
以下の処理でシェルの種類に依存せず(とは言っても bourne shell 系のみだが) シェルスクリプト自身のパスを取得する事ができる筈(多分)。
PATH 環境変数に従って実行された場合は ${0} にスクリプトの絶対パスが格納されているので ${0}dirname (1) を取得すれば良いが、 相対パス指定で実行された場合は 1度 cd (1) した上で pwd (1) を実行してカレントディレクトリを取得する必要がある。
すべてのケースで "( cd ${0%/*} `dirname ${0}` && pwd )" しても同じ結果を得られるのだが、 サブシェルの実行や特に pwd (1) の実行はシステムに負荷をかけるので、 効率を考え ${0} の値を確認している。
expr (1) の実行も結構負荷がかかるからあまり意味ないかな…

  1#!/bin/sh
  2# ${0} の dirname を取得
  3# cwd=${0%/*}
  4cwd=`dirname ${0}`
  5
  6# ${0} が 相対パスの場合は cd して pwd を取得
  7expr ${0} : "/.*" > /dev/null || cwd=`(cd ${cwd} && pwd)`
  8    :
    

2011/03/17 追記

$ sh foo
	
この様に実行された場合 ${0} には foo が 格納されているので ${0%/*} では foo に展開されてしまい cd (1) がエラーとなる問題があったので、 dirname (1) を利用する様修正しました。

2011/02/09

ファイル暗号化/復号化 wrapper スクリプト

openssl (1) を実行してファイルを暗号化/復号化する処理を 簡易実行するための簡単な シェルスクリプトによる wrapper を作成した。
暗号化/復号化は openssl (1) の enc コマンドに 暗号化アルゴリズムに aes-128-cbc を指定して実施している。
指定されたファイルの先頭 8 バイトを参照して Salted__ の場合は暗号化されていると仮定し復号化、 それ以外は暗号化する処理をデフォルトで実行するが、 実行時オプション -d-e を指定する事で 強制的に暗号化/復号化を指定する事も可能だ。
-p オプションでパスワードを指定してバッチ処理も実行できるが、 コマンド実行履歴等にパスワードが残るのでお勧めできない。
暗号化/復号化が成功した場合は元のファイルを置き換える。

例によって必要に迫られれて適当に作成したスクリプトなので このスクリプトを利用した事で生じるあらゆる損害に対して責は負えない。

2011/01/17

シェルスクリプトで疑似乱数を取得する

gnu bash には ${RANDOM} というシェル変数が用意されていて、 アクセスするたびに疑似乱数(風)の値が取得できる様だ。 しかし posix 準拠の機能ではなく bash 独自の機能なので拡張性がない。 そこで汎用的な疑似乱数取得の方法として awk (1) を利用した方法を使ってみる。

awk (1) には rand() という関数が組込まれているので 乱数生成ができる。 その際に利用される種(seed)は srand() という関数で初期化できるので、 これらを利用する事でそこそこの精度の疑似乱数は取得できる。
たとえば 0 〜 m までの疑似乱数は 取得した値から m の剰余を取ることで取得できる。
ただし awk (1) の rand() は仕様として 0 〜 1 までの桁数不定の少数を返すので、 乱数として利用する場合には整数に変換する必要がでてくる。
整数にするために 10n を乗すればよいのだが、 小数点以下の桁数が不定のために小さすぎる n を乗すると 全ての桁が整数化されずに乱数の精度が低くなってしまい、 逆に大きすぎる n を乗すると値が xxx000 の様になってしまい 剰余を取得しても無意味になってしまう。

そこで awk (1) により疑似乱数を取得する場合は rand() で取得した値の前 2 文字 ("0.") を文字列として除外した値から m の剰余とする事で 0 〜 m までの乱数が取得できる。

  1#!/bin/sh
  2
  3awk 'BEGIN{
  4    srand();
  5    print substr(rand(), 3) % '${1:-1}'
  6}'
    

データの型が存在しない(文字列であり数字である) awk (1) ならではの裏技とも言えるだろう。

2011/01/06

htaccess で特定のファイルのみパスワードを要求しない

Web コンテンツを保護するために .htaccess ファイルを用いて Basic 認証などを実施する場合は多い。
通常 .htaccess はディレクトリ単位で有効になってしまうのだが、 あるディレクトリのアクセスを Basic 認証でアクセス制御したいが 特定のファイルについては認証を要求しない設定を行いたい場合は Files ディレクティブと Satisfy ディレクティブで実現できる。

AuthType        Basic
AuthUserFile    認証用ファイル
AuthName        "Enter password"
Require         valid-user
<Files "認証要求しないファイル">
    Satisfy     Any
    Allow       from all
</Files>
	

Satisfy ディレクティブは Allow ディレクティブと Require ディレクティブがどちらも使われている場合の アクセスポリシーを制御する。
Any が指定された場合は AllowRequire のどちらかの条件を満たせばアクセスが許可されるので、 Files ディレクティブで指定したファイルに対しては Allow 指定が有効になり認証なしでアクセスが許可される。

逆にある特定のファイルだけの Basic 認証によるアクセス制御は Files ディレクティブのみで可能である。

AuthType        Basic
AuthUserFile    認証用ファイル
AuthName        "Enter password"
<Files "認証要求するファイル">
    Require     valid-user
</Files>
	

どちらの場合も Files ディレクティブは以下の様に ~ を使う事でファイル名を正規表現で記述できる。

<Files ~ "\.(gif|jpe?g|png)$">
	:
</Files>
	
apache では PCRE - Perl Compatible Regular Expressions を 利用しているので複雑な正規表現の記述ができる様だ。

2010/12/15

DHCP

先日購入した MacBook Air を自宅のネットワークに接続しようとした所、 何故か DHCP での IP アドレス取得に失敗してしまう現象が発生した。 Windows Xp や FreeBSD がインストールされた PC では正しく取得できるが、 MacOS X ではどうやっても IP アドレスが取得できない。 無線 LAN 接続のアクセスポイント(TimeCapsule)の設定を変更したり、 アクセス制御を解除してみても全然 IP アドレスが取得できず DHCP サーバの設定を何度も確認しても症状はいっこうに改善されない。

そこでネットワーク障害はパケットキャプチャが基本だと思い立ち、 IP アドレスが取得できない MacBook Air で tcpdump (1) を実行すると、 クライアントからの DHCP DISCOVER に対して サーバは DHCP OFFER を応答しているのだが、 パケットの Source IP Address が 127.0.0.1 となっている事を発見した。

なぜ DHCP OFFER パケットの Source IP Address が 127.0.0.1 だったのか、 結論から言うと /usr/local/etc/dhcp.conf ファイル中の option domain-name に設定した FQDN が /etc/hosts127.0.0.1 で登録されていたため、 DHCP サーバがパケットを送信する際に domain-name を逆引きした結果として 127.0.0.1 を Source IP Address に設定してしまった様だ。
/etc/hosts から該当する FQDN のエントリーを削除して、 DHCP サーバを再起動した所 IP アドレスが取得できた。

FQDN を 127.0.0.1/etc/hosts に登録する事は Linux の一部のディストリビューションなどでは普通に行われている様だが、 メイルが送信できない、DHCP が機能しないなどの障害発生の原因になるので 是非とも辞めて欲しい。

それにしてもこの MacOS X の DHCP クライアントは Source IP Address が 127.0.0.1 の DHCP OFFER を無視しちゃうのね。

2010/09/01

mh で画像を添付したマルチメディアメイルを送信する

最近の mh(1) は標準で画像等を添付した MIMEマルチパート形式のメイルが送信できる。
mh(1) では mhn(1) コマンドを利用して マルチメディアメッセージを操作するので、 マルチメディアメイルを送信するためには、 本文中にマルチメディアメイルである事を通知する行 (ここでは mhn 通知行 と呼ぶ)を記述した上で mhn(1) コマンドを実行し、 添付ファイルを base64 エンコードしてマルチパート形式に変換すればよい。

mhn 通知行は本文の 1 カラム目から以下の形式で記述する。

#MIME タイプ; name="ファイル名" [ファイルの説明] ファイル名
MIME タイプは jpeg 形式の画像であれば image/jpeg、 gif 形式の画像であれば image/gif などと指定する。
comp(1) や repl(1) を利用してメイル本文を編集する場合、 mhn 通知行を含む本文を作成した後で What now? プロンプトから edit mhn などとして mhn(1) コマンドを実行してから 送信すればマルチメディアメイルが送信できる。

最近の日本語パッチが適用された mh(1) は、 mhn(1) コマンドがメイル本文の文字コードを参照して 適切な charset を Content-Type: ヘッダに付加するので、 メイル送信前に必ず mhn(1) を実行しても良いだろう。
その場合は $HOME/.mh_profile に以下の行を記述しておくと 送信時に自動で mhn が実行されて便利。

automhnproc:	mhn

ちなみに 1 カラム目が # な行は mhn 通知行 とみなされるので、 本文中で # が行頭になるメイルを作成する場合は ## とする必要がある。

この様に mh(1) で MIME マルチパート形式のメイルを送信するのは 最近の高機能な MUA に比較すると若干面倒なので、 多少なりとも簡単に送信するために mhmime スクリプトを作成した。
このスクリプトを利用してマルチメディアメイルを作成するためには メイル本文の 1 カラム目から以下の行を記述する。

#MIME ファイル名 ファイルの説明
このスクリプトは記述されたファイル名から MIME タイプを推測して mhn 指示行 を生成し、 #MIME 以外で 1 カラム目が # の場合は ## に置換した上でmhn(1) コマンドを実行する。

メイル本文を作成した後で What now? プロンプトから edit mhmime などとしてこのスクリプトを実行した上で 送信すればマルチメディアメイルが送信できる。
$HOME/.mh_profileautomhnproc: に指定しておけば、 送信時に自動で実行されるので多少は便利になるかもしれない。

しかし、今時 mh を素で利用している人は果たしてどれほどいるのだろうか?

2010/08/17

SwiftPoint

Swiftpointが発売した 超小型のモバイルマウスが到着したので、 早速開封して MacBook に接続してみる。
自然に曲げた人差し指が丁度触れる位置に通常の左クリックボタン、 その手前に右クリックボタンがあるので、 特に右クリックボタンは最初のうちは意識しないと押し辛い気がする。
左クリックボタンの外側に設置されたスクロールホイールは、 指先で回転させても、本体を少し傾けて本体を上下させる サイドスクロールでもなかなか使い易いので良いアイデアではないだろうか。

Image: IMG_0413.JPG

Image: IMG_0414.JPG

ペンを握る時の様な自然な持ち方で利用するので 細かな操作も可能という触れ込みなのだが、 一般のマウスとは若干異なる操作感なので慣れるまでには多少時間が必要そうだ。

2010/06/02

みずほ銀行

みずほ銀行のオンラインバンキングで振り込みをする場合に必要な 第2暗証番号から指定された4桁の番号を見つけ出すためのスクリプト。
awk (1) だけで書いたのでどんな環境でも動作する筈。
引数で番号を指定するか端末から入力すると、 対応する数字が表示されます。
こんなピンポイントでしか役立たないスクリプトを 利用する人がいるかどうか不明なのだが、 折角なので公開だけはしてみる。
あまり問題はないと思うのだが、 第2暗証番号を平文で保存するので ご利用はくれぐれも自己責任で。

  1#!/bin/sh
  2#
  3# $Id: mizuho,v 1.1 2010/01/06 07:15:54 mitz Exp $
  4#
  5awk '
  6    BEGIN{
  7        base="第2暗証番号"
  8        if("'$1'")
  9            num = "'$1'"
 10
 11        if(!match(num, /^[0-9]{4}$/)){
 12            printf "Input number: "
 13            getline num < "/dev/tty"
 14        }
 15        split(num, nums, "");
 16        for(i=1; i<=4; i++)
 17            print substr(base, nums[i], 1)
 18        print
 19    }
 20' < /dev/null
    

2010/05/13

ファイルの逆順出力

ファイルを逆順に出力したい事がたまにある。
FreeBSD の tail (1) には -r オプションがあって ファイルを行単位で逆順に出力できるが、 これは POSIX.2 にはない拡張仕様なので汎用的ではない。
Linux では tac (1) (多分逆順に出力する cat だから tac) というコマンドがインストールされている事もあるが、 これも POSIX.2 には存在せず Linux でも標準ではインストールされていない場合がある。

ファイルの逆順を出力するなら ex (1) を利用して、

$ ex -s ファイル <<-FOF
>	g/^/mo0
>	%p
>EOF
とするのが汎用的で良いと思う。

簡単に解説すると「行の先頭 (^) を 0 行目に移動(mo0)して、 全行を表示する(%p)」というコマンドを実行している。
行の先頭は全ての行に存在するので全ての行が処理対象になる。 各行を順番に 0 行目(1 行目の前の行なので先頭行)に移動するので、 結果としてファイルの内容が逆順に表示される。


Copyright © 2008-2020 Mitzyuki IMAIZUMI. All rights reserved.