パスワードを忘れた? アカウント作成
13479416 journal
日記

dodaの日記: SSH での AES-GCM の利用 2

日記 by doda

一つ前の日記で、SSH 接続での AES-GCM の利用を勧めましたが、一部では AES-GCM は危険だと誤解している人がいるみたいなので、
少なくとも SSH での AES-GCM の利用は安全だという事を書いてみようと思います。

AES-GCM が危険だという誤解は、どうも『本当は怖いAES-GCMの話』というページの影響を受けているように思います。
この『本当は怖いAES-GCMの話』に書かれている内容自体には問題は有りません。
# タイトルが AES-GCM 全般が危険なように思わせる物になっているのは気に入りませんが
しかし、『本当は怖いAES-GCMの話』は殆どが TLS 1.2 での AES-GCM の利用について書かれており、
AES-GCM 全般、特に SSH での AES-GCM にはそのまま当て嵌められません。

数学的に安全が保証されているGCMですが、それはGCMが使うIV(初期ベクトル)が再利用されないこと、
すなわちIVがNonce(Number used once)であることが大前提となっています。この前提が崩れると
AES-GCMの安全性は大きく損なわれます。

この部分は GCM 全般について書かれています。GCM で IV (Nonce) が再利用された場合は安全性が大きく崩れるのは事実です。
しかし、これは GCM に限った話ではなく、他の (IV を使う) 暗号方式でも IV を再利用した場合は同様に安全性が損なわれます。
その為、GCM の利用時に限らず IV (Nonce) は再利用する事が無いように決める必要があります。

今回の調査で、幸いこの脆弱性の影響を受けるのは一部実装に限られており、(素のままの)OpenSSLは問題ありません。

この AES-GCM の IV 再利用の問題は、一部の実装の問題であり、正しく AES-GCM を使えば問題は無いという事ですね。
ただ、実装によっては AES-GCM で IV が再利用するがあるというのは、そのような状況が起こりえるようになっている
TLS 1.2 のプロトコルの問題とも言えます。SSH での状況については後述します。

TLSで暗号化されたデータの頭に明示的に8バイト分のIVが付与されています。当然この部分は暗号化されていないので攻撃者
からはHTTPSサーバがどのようなIVを使っているのか丸見えです。

IV 自体は(正しく運用されていれば)外部に見えても問題は有りません。しかし、IV が再利用された場合にそれを外部から
簡単に検出出来る事になるので、IV が外部に見えるという事が攻撃を行い易くしたというのは有ると思います。
SSH では通信内容には IV は含まれません。

さらなる調査結果から、7万以上のサーバが乱数を使って初期ベクトルを毎回生成しているのがわかりました。
この方式では、大量のデータの通信を行うと過去使った乱数値と同じ乱数を生成してしまう確率が格段に上昇します。

これは TLS 1.2 の AES-GCM では IV の生成方法が決まっていなかった為、大量の通信が行われる状況では問題が
発生する方法を取った実装があったという事ですね。
SSH では IV の生成方法が決まっており、実装によって問題が発生するような決め方をする事は出来ません。

乱数でNonceを生成するには時代的にもう合わなくなってきました。そのため他の実装では、通常IVにカウンター値を利用します
(Nonceは再利用されなければ予測可能であっても構わない)。この場合、IVは2^64まで一意に生成できるのでまぁ大丈夫でしょう。
OpenSSLでは一番最初の値を乱数で決め、それ以降はカウンターとしてインクリメントしていく実装になっています。

SSH での IV の生成方法は、この OpenSSL での方法に近いです。
初期値は鍵交換の結果から計算で生成され、それ以降はカウンターとしてインクリメントしていきます。
プロトコルとしてこのように決まっている為、他の方法が使えない(使おうとすると通信が行えない)ようになっています。
またカウンターが一周するはるか前に鍵の再交換によって別の鍵での通信になる為、一周して同じ値になっても問題は発生しません。
# 実際には鍵の再交換によって新しい IV の初期値が使われるようになるので、IV が一周する事は無いでしょう

このように、SSH の AES-GCM では IV が再利用される事がないような方法を使う事がプロトコルで決められているので、
特定の実装の問題を気にする事もなく安心して AES-GCM を利用する事が出来ます。

13479277 journal
ソフトウェア

dodaの日記: Tera Term 4.97 2

日記 by doda

既に2週間前ですが、Tera Term 4.97 をリリースしました。
全ての変更点はリリースページの変更履歴をみてください。

今回の変更内容の内、お気に入りの物として以下が有ります。

    ・SSH2 の共通鍵暗号方式として以下をサポートした。
        ・aes128-gcm@openssh.com
        ・aes256-gcm@openssh.com
    ・SSH2 の MAC アルゴリズムとして以下をサポートした。
        ・hmac-sha1-etm@openssh.com
        ・hmac-sha2-256-etm@openssh.com
        ・hmac-sha2-512-etm@openssh.com
        ・hmac-ripemd160-etm@openssh.com
        ・hmac-md5-etm@openssh.com
        ・hmac-sha1-96-etm@openssh.com
        ・hmac-md5-96-etm@openssh.com

共通鍵暗号方式(通信路の暗号化に使われる)に追加した AES-GCM は認証付き暗号(AEAD)という物で、
暗号化と同時にメッセージ認証(正しい送信者から送られたか、改竄されていないかチェックする)機能も持った物です。

SSH のメッセージ認証機能としては通常は MAC が使われますが、SSH での MAC の利用方法(E&M)では一旦パケットを復号してから
MAC の検証をする必要が有り、選択暗号文攻撃に対して不安が有りました。

一方 AES-GCM のような AEAD では復号と同時にメッセージの検証が行える為、選択暗号文攻撃を防ぐ事が出来ます。
AES-GCM は他の暗号化方式と比べて安全だと考えられるので、これを優先して使う事をお勧めします。
Tera Term でも新規インストール時のデフォルト設定では aes256-gcm@openssh, aes128-gcm@openssh.com を最優先するようになっていますが、
アップグレードインストールでは既存の設定が優先されるため、「設定」-「SSH」にある「優先する暗号アルゴリズム」で aes256-gcm@openssh.com,
aes128-gcm@openssh.com の優先度を上げる事をお勧めします。

もう一つの追加内容である MAC アルゴリズムですが、これは MAC の利用方法として EtM という方式を追加する物です。
前述したように SSH の MAC の利用方法(E&M) ではメッセージの復号の前にメッセージの検証が出来ません。
EtM は MAC の利用方法を変更して、復号の前にメッセージの検証を行えるようにした物で、これも選択暗号文攻撃に強くなります。
# E&M, EtM の詳細については前述の 認証付き暗号 を参照して下さい。

現在では E&M より EtM の方が安全だとみなされていますので、こちらの方も優先度を上げる事をお勧めします。
優先度を上げるのは、hmac-sha1-etm@openssh.com, hmac-sha2-256-etm@openssh.com, hmac-sha2-512-etm@openssh.com の
三つの方式でいいでしょう。
# 設定を変更した後は、「設定」-「設定の保存」を忘れずに

13003207 journal
ソフトウェア

dodaの日記: Chocolatey のパッケージ 2

日記 by doda

Windows 用のパッケージ管理システムとして Chocolatey という物があります。
この Chocolatey に誰かが Tera Term のパッケージを登録していたのですが、2 年前のバージョンのまま更新が行われていませんでした。
この状態はあまり望ましくないので、最新版に更新してみました。
https://chocolatey.org/packages/teraterm/

使い方ですが、Chocolatey 自体のインストール方法は省略します。
使った事がない人は https://chocolatey.org/install を見たり、"chocolatey インストール" で検索したりしてインストールして下さい。

Chocolatey で Tera Term をインストールする場合、管理者権限のコマンドプロンプトまたは PowerShell の プロンプトから

choco install teraterm

と入力します。途中でインストールスクリプトを実行していいか確認されるので、y を入力して実行します。
インストール先やインストールオプション等はデフォルトとなりますが、既に Tera Term をインストール済みの場合はその設定を引き継いで最新版に更新されます。

以降は新しいリリースが出た時に

choco upgrade teraterm

を実行すると最新版に更新されるようになります。

パッケージの登録後に Chocolatey 側での承認が必要なので利用出来るようになるまで多少タイムラグがありますが、大体1日程度有れば利用できるようになるはずです。
4.93 の時の実績だと、

02:30 Tera Term 4.93 リリース
11:30 Chocolatey パッケージのアップロード
21:10 Chocolatey 側での承認

というような感じでした。

一度設定すれば以降の更新が簡単に出来るようになるので、試してみてはどうでしょうか。

12778216 journal
バグ

dodaの日記: Tera Term 4.90 のデフォルト設定で古い Solaris のサーバに繋がらない

日記 by doda

問題点:
Tera Term 4.90 をデフォルト設定で使っていると、古い Solaris のサーバ(Solaris 9 だけ?)に以下のメッセージが出て接続出来ない。

unknown KEX algorithm: diffie-hellman-group1-sha1

とりあえずの解決法:
Tera Term の「設定」-「SSH」にある「優先する鍵交換アルゴリズムの順」で "diffie-hellman-group1-sha1" の優先順位を一つ(以上)上げる。

お勧めの解決法:
Solaris のサーバに最新の OpenSSH をインストールして使う。

……というバグを入れてしまいました。orz
変更履歴でいうと

鍵交換方式ですべての方式を有効にしている時に最後の方式が使われない問題を修正した。

という奴です。

このバグが入った背景ですが、ssh の通信経路の暗号化やホスト鍵としてより安全な新しい方式が出て来ているので、
それに合わせて鍵交換方式でも安全な方式を追加しようという動きがあり、Internet-Draftが書かれました。
Tera Term 4.90 ではこの Internet-Draft で追加された新しい方式に対応しました。

ssh の鍵交換では、利用する鍵交換方式の候補を , で繋げた文字列として送るのですが、新しい方式が増えた事でこの時に送る文字列も長くなります。
そして、対応している方式を全部有効にした場合の鍵交換方式のリストが長くなりすぎて、処理に利用しているバッファに収まらなくなってしまいました。
その為、一番後ろにある鍵交換方式名を途中で切り詰めて送ってしまい、サーバ側でその方式が正しく認識できず使われなくなりました。
この一番後ろになる鍵交換方式は優先度が一番低く設定した物になります。デフォルト設定では diffie-hellman-group1-sha1 が該当します。
そして、Solaris 9 で使われている SunSSH 1.0 では鍵交換方式としてこの diffie-hellman-group1-sha1 しか使えない為、鍵交換が行えなくなりました。

という事で、とりあえずの対処としては最初に挙げた「diffie-hellman-group1-sha1 の優先度を上げる」方法になります。
しかし、diffie-hellman-group1-sha1 は 1024 ビットの強度しかなくしかも SHA-1 を利用している為、今となってはかなり弱い方式です。
最新の OpenSSH ではデフォルトでは無効にされていますし、Tera Term でも将来のバージョンではデフォルトでは無効化する事を検討しています。
なので、このような安全では無い方式を使わずに、最新の OpenSSH を入れてそちらを利用する事をお勧めします。

2016/6/1追記:
実は他にも Juniper の SSG や Cisco の一部の(古い)機器などでも問題が出たらしいです。
Tera Term を最新の 4.91 にバージョンアップすればデフォルト設定でも接続できるようになります。

Cisco の機器に関しては一部の機器が diffie-hellman-group-exchange-* (GEX) で大きいグループサイズを受け付けないという問題が有って対処を入れたりした事から
普通は GEX に対応しているもんだと思っていましたが、diffie-hellman-group1-sha1 のみの機器(IOSのバージョン?)も有ったのかと意外でした。

こうなると diffie-hellman-group1-sha1 の無効化は簡単に出来ないなあ。

12736192 journal
日記

dodaの日記: シリアルコンソール設定のCentOS 7.2が起動時に固まる 3

日記 by doda

DELL PowerEdge R210にCentOS 7.2(1511)をインストールしたのだけど、シリアルコンソールの設定(後述)をしてから、
起動時にシリアルポートに起動途中で止まるという現象が出て悩んでいる。
止まるタイミングですが、grubのメニューの後、systemd?が数行メッセージを出力した所で先に進まなくなる。
この止まった状態でシリアルポートに端末を接続すると、モニタおよびシリアル端末にブートメッセージの続きが出力されるようになって正常に起動する。
最初からシリアルポートに端末をつないでいる場合、途中で止まる事なくそのまま起動する。

シリアルコンソールの設定内容:

1. /etc/default/grubの以下の行を変更

GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet"

GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet console=tty0 console=ttyS0,115200n8r"

2. grub2-mkconfig -o /boot/grub2/grub.cfg を実行
3. 再起動

CentOS 6の頃はシリアルコンソールの設定をしても特に問題は出なかったんだけれどなあ。
原因とか対処方法とか教えて、偉い人!

12660269 journal
ソフトウェア

dodaの日記: 背景色でも強調がしたい! 2

日記 by doda

この日記はかなり前に途中まで書かれた後飽きてしばらく寝かされていました。
どれくらい寝かされていたかはタイトルから察してください。

複数の端末ウィンドウを開いて作業している時で、root でログインしているとか本番サーバに入っている場合などに、
特に注意を払って作業をする必要があるウィンドウである事を強調したい事があると思います。
よく使われる方法はプロンプトで目立たせる方法ですが、目立ち方が足りないと思う人がいますし、
vi でファイルの編集をしている時などはそもそもプロンプトが表示されなかったりします。

さらに目立つ方法として、端末の背景(と文字)の色を変えるという事も行われる事があります。
よく行われる方法としては、重要な作業をする場合は他と違う背景色の端末エミュレータを起動して
そこで作業をするという物があります。
しかしこの方法の場合、通常の作業をしている端末で root になった場合には対応できません。
そこで今回紹介するのは、動的な文字/背景色の変更方法です。

端末エミュレータの事実上の標準である xterm には、起動後に文字色,背景色を動的に変更する為の制御文字列があります。
この制御文字列は Tera Term や mlterm, rxvt-unicode, ICE IV 版 PuTTY 等でもサポートされていて、それなりに汎用的に使えます。
この制御文字列を例えば root のプロンプトに埋め込む事によって、root になった時に自動で背景色が変わるようにする事が出来ます。

制御文字列の形式:

   OSC 1 0 ; 色指定 ST      -- 文字色を"色指定"の色に変更する
   OSC 1 1 ; 色指定 ST      -- 背景色を"色指定"の色に変更する
   OSC 1 1 0 ST             -- 文字色をデフォルトの色に戻す
   OSC 1 1 1 ST             -- 背景色をデフォルトの色に戻す

OSC は文字 0x9d の事ですが、通常は7ビット表現である ESC(0x1b) ] が用いられます。

同様に ST(0x9c) は ESC \ が用いられます。
OSC 文字列の終端は正式には ST なのですが xterm 等では BEL(0x07) も使われたりします。
一部の端末(CDE の dtterm 等)では ST を認識せず端末がハングアップしたような状態になる事が有るので、BEL を使用する方が無難かもしれません。

色指定には、通常は #rrggbb のような形式が用いられる事が多いです。
rr, gg, bb は 16 進での 2 桁の値で、それぞれ RGB での赤, 緑, 青の各色の明るさを表します。

動作確認:
接続先のホストで以下のコマンドを実行すると、対応している端末では赤背景に白文字の状態になります。

% echo -e '\e]10;#ffffff\a\e]11;#ff0000\a'

上記の例では文字色を変更する OSC 文字列と背景色を変更する OSC 文字列の二つを使用していますが、
下記のような、一つの OSC 文字列で文字色と背景色を変更する短縮形式が有ります。

% echo -e '\e]10;#ffffff;#ff0000\a'

ただし、この形式は対応していない端末が多いので、いろいろな端末を使う場合は避けた方がいいかもしれません。

以下のように OSC 110, 111 を使うと端末の色をデフォルトにリセットする事が出来ます。

% echo -e '\e]110\a\e]111\a'

ただし一部の端末(rxvt-unicodeやmltermなど)ではこのリセットに対応していないので、これらの端末を使う場合は
OSC 10, 11 で初期状態と同じ色に設定する方がいいかもしれません。

設定:
端末色の変更が確認できたら、後は適切なタイミングで色の変更が行われるようにすれば OK です。
しかし、root へのユーザ変更をどのように行うか、例えば su を使うのか sudo を使うのか、
またオプションに何を指定するのかによって起動するシェルや読み込まれる設定ファイルが変わってきます。
ここでは一つの例として、zsh を使用しているユーザが sudo -Hs を使って root 権限を得る場合の設定を書きます。

まず sudo -Hs で root になった場合、root のホームディレクトリの .zshenv, .zshrc の二つの設定ファイルが読み込まれます。
.zshenv は対話型シェルじゃなくても読み込まれますので、ここでは .zshrc に以下の設定を追加します。

echo -ne '\e]10;#ffffff\a\e]11;#ff0000\a'

これで sudo -Hs で root になった時に端末の色が白文字で赤背景になります。
他の色にしたい場合は、#ffffff, #ff0000 の部分を変更してください。

root になった時に色を変えるだけだと、一般ユーザに戻ってもウィンドウの色が変わったままとなるので紛らわしくなります。
そこで、root から戻った時にウィンドウ色を元に戻すために、.zshrc に以下の行を追加します。

trap 'echo -ne "\e]110\a\e]111\a"' 0

これで sudo -Hs で起動したシェルが終了する時に echo コマンドが実行されて、端末の色がリセットされます。
OSC 110, 111 による色リセットが使えない端末の場合、以下のように別の色(この例では白文字に黒背景)に変更するようにします。

trap 'echo -ne "\e]10;#ffffff\a\e]11;#000000\a"' 0

最後に:
自分の場合はこの設定を入れてはあるのですが、普段は sudo コマンドで必要なコマンドのみを実行するようにしており、
root 権限のシェルを起動する事はほとんど無いので、実際のところこの設定が使われる事がまず無いです。
しかし、ごくまれに一般ユーザが入れないディレクトリへ移動する事が必要になった時などに sudo -Hs を実行して
いきなり背景色が変わって驚くという事を繰り返しています。
背景色が変わると普段とは違う状況だと一目瞭然なので、それなりに役に立っていると思います。

12517611 journal
日記

dodaの日記: PuTTYの秘密鍵が独自形式な理由

日記 by doda

PuTTY では認証に使う秘密鍵の保存に独自の形式(PPK形式)を使いますが、これはなぜか、
あと関連して ssh の公開鍵認証のやりとりと OpenSSH の ssh クライアントの挙動に
ついての話です。

結局のところはここに書いてあるように PPK 形式の方が優れている
(OpenSSH の秘密鍵の形式には欠点がある)という事なんですが。

ssh での公開鍵認証のやりとりは以下のような流れです。

1. クライアントが「公開鍵認証だけどこの公開鍵は使える?」と公開鍵を送る
2. サーバが「その鍵は使えるよ/使えないよ」と答える
3a. 「使えないよ」と返ってきた場合、1 に戻って他の公開鍵を試したり、別の認証方式を試す
3b. 「使えるよ」と返ってきた場合、「この公開鍵で認証するよ、署名はこれね」と公開鍵と、
        認証用のデータを秘密鍵で署名してその署名を送る。
4. サーバは公開鍵と署名を確認し、認証が成功したか失敗したかを返す

1~2で使える公開鍵の確認をしていますが、これは余計な署名を行わない為です。
秘密鍵は通常暗号化してあり、署名をする時にはパスフレーズが必要になります。
例えば秘密鍵として id_rsa と id_ecdsa の二つが有り、サーバ側の authorized_keys に
id_ecdsa の公開鍵が登録されている場合、いきなり署名して送る方式(プロトコル的にはこれも許される)だと

1. id_rsa で署名(パスフレーズが要求される)して認証要求を行い、認証が失敗する
2. id_ecdsa で署名(パスフレーズが要求される)して認証要求を行い、認証が成功する

というようにパスフレーズ入力が二度必要になります。
事前に公開鍵が使えるかの確認が入る事で id_rsa で署名する為のパスフレーズ入力が必要なくなります。
また署名自体が重い処理である為、秘密鍵にパスフレーズが付いていなくても
よけいな署名を行うのを避けられる事には意味があります。
# まあ今時の環境だと署名の重さは気にならないでしょうが

ここで秘密鍵の形式が問題になってきます。
秘密鍵のファイルの中には公開鍵の情報も含まれています。
しかし OpenSSH の秘密鍵形式では全体が暗号化されている為(*1)、秘密鍵ファイルの中から
公開鍵を取り出す為にはパスフレーズが必要になります。
これでは使えない鍵に対するパスフレーズの入力が避けられません。
そこで OpenSSH では "秘密鍵のファイル名.pub" というファイル、例えば id_rsa.pub が有ったら
それを秘密鍵に対応する公開鍵として扱います。
これによってパスフレーズ無しに公開鍵が使えるかの確認が行えるようになりましたが、
秘密鍵だけを置き換えるなどの原因で秘密鍵と公開鍵の対応が取れていない時は
認証が行えなくなるという問題が出ます(*2)。

一方、PPK 形式では公開鍵の部分は平文で保存されている為、パスフレーズ無しで公開鍵が取り出せます。
また秘密鍵ファイル一つで完結している為、秘密鍵と公開鍵の対応が取れていないという問題も発生しません。

PPK 形式の利点としては公開鍵部分も含めて全体が MAC で守られているので改竄が出来ないというのもありますが、
これについては省略します。

という事で PuTTY が秘密鍵に独自形式を使っているのは自己主張とか嫌がらせとかじゃなくちゃんと理由があるんです。

2020/02/19 追記:
*1: OpenSSH の秘密鍵形式では全体が暗号化されている
ここで OpenSSH の秘密鍵形式と言っている物は、正確には OpenSSL の PEM 形式です。
OpenSSH 6.5 から新しい OpenSSH 独自の秘密鍵形式が導入されましたが、この形式では公開鍵部分は暗号化されていません。しかし PEM 形式との互換性の為か、秘密鍵ファイルがこの形式でも公開鍵ファイルが存在する場合はそちらを優先するという動作は変わっていません。

*2: 秘密鍵と公開鍵の対応が取れていない時は認証が行えなくなる
OpenSSH 7.6 からはこのような時には "identity_sign: private key /home/user/.ssh/id_rsa contents do not match public" のような警告メッセージが出てその鍵での認証を行わなくなるので、問題に気づき易くなっています。

12511074 journal
日記

dodaの日記: 端末がびよんびよんしたりぴょんぴょんしたり 4

日記 by doda

元ネタはこの辺

EmacsやVimがびよんびよんしたり、ぴょんぴょんしたりしているのを見て、
「これ、ターミナルエミュレータ一般で出来るんじゃね」と思ったので作ってみた。

どちらも dtterm のウィンドウ操作/情報取得シーケンスを利用している。
以下、簡単な解説。

・端末のウィンドウが勝手にびよんびよんなってたのしいやつ

dtterm の端末サイズ変更シーケンスを利用している。

xterm, urxvt, mlterm, Tera Term, PuTTY, RLogin で動作するのを確認。
iTerm2 は動くけれど Ctrl-C で止まらないという話を聞いているけれど、
試せる環境が無いので詳細は不明。
# 9/13追記: mintty+cygwin, AbsoluteTelnet, ZOC でも動きました

元の端末サイズの取得には stty -a の出力を利用しているが、OS によって微妙に
フォーマットが違ったので動かないのもあるかも。
端末サイズの取得も dtterm のシーケンスを利用するという方法もあるが、情報取得は
応答を受けるのが面倒なので避けた。
io/console で取得するという手もあるが、ruby 1.8 でも動かしたかったのでこれも避けた。

やっている事は端末のサイズを指定した大きさに変更するシーケンスを出力しつづけるだけなので、
sin() と cos() さえなんとか出来ればシェルスクリプトでも作れるはず。

・あぁ^~端末がぴょんぴょんするんじゃぁ^~

dtterm の以下のシーケンスを利用している。

  • 端末サイズ取得 (文字単位)
  • 端末サイズ変更 (文字単位)
  • ウィンドウサイズ取得 (ピクセル単位)
  • ウィンドウ位置取得 (ピクセル単位)
  • ウィンドウ位置変更 (ピクセル単位)
  • ルートウィンドウサイズ取得 (文字単位)

これら全部が問題なく使える端末が意外と無く、試した範囲では xterm と Tera Term でしか動かなかった。
# 9/13追記: mintty+cygwin でも動きました

ぴょんぴょんさせる範囲を得る為にルートウィンドウのサイズを取得するが、
これは文字単位での大きさなので一文字の大きさを調べる必要がある。
そこで取った方法は、まず端末サイズを 81x25 に変更してウィンドウサイズを取得する。
そして次に端末サイズを 80x24 に変更してウィンドウサイズを取得し、81x25 の時との差から
一文字の大きさを求める。
これで動かす範囲が決まるので、あとは適当にぴょんぴょんしている感じに端末の位置を移動させる。

こっちも頑張ればシェルスクリプトでも作れるかも。

12005932 journal
ソフトウェア

dodaの日記: OpenSSH 6.8 と Tera Term

日記 by doda

先月出た OpenSSH 6.8 なサーバに Tera Term で接続すると、認証後に

Unexpected SSH2 message(80) on current stage (6)

というエラーメッセージを出して接続が切られるという問題があります。
これは OpenSSH 6.8 で追加された hostkey rotation 機能のパケットを
Tera Term が正しく扱えていなかったからです。

とりあえずはこのパケットを無視するようにしたので次のバージョン
(Tera Term 4.87/ttssh2-2.73) では接続できるようになります。
# hostkey rotation にもその内対応する予定です

Tera Term 4.87 は5月末にリリースする予定で、急いで OpenSSH 6.8 に
上げる人もそんなにいないだろうと思っていたのですが、エラーが出ると
言っている人をちょくちょく見かけるのでどうした物かと考えていました。

# 一応、差し替え用の ttxssh.dll を準備はしてあります。
# http://ttssh2.osdn.jp/snapshot/ttxssh-2.72-OpenSSH68.zip

そんな中、FreeBSD ports の security/openssh-portable にこの問題の
対策の為のパッチがコミットされ、openssh-unix-dev ML にも
このパッチが報告されました

パッチの内容はクライアントのソフトウェア名を見て、問題があるバージョン
だったら hostkey rotation のパケットを送らないようにするという物でしたが、
このクライアントソフトウェア名の判定がちょっと雑で、ttssh だったらすべての
バージョンで無効にするようになっていました。
これだと将来 ttssh2 が hostkey rotation をサポートしても使われない事に
なってしまうの、せめてバージョンを確認するようにしてくれと変更を提案した所
無事受け入れられました。

という事で、OpenSSH 6.9 以降では旧バージョンの Tera Term でも問題なく
繋がるようになります。
また ports の openssh-portable にもほぼ同じパッチが入っているので、
ports tree を更新して OpenSSH 6.8 を再インストールすれば Tera Term で
問題なく繋がるようになります。

9993565 journal
ソフトウェア

dodaの日記: vimでの縦分割時のスクロール速度改善

日記 by doda

vim や tmux などで縦分割(*1)を行うと「遅い」とか「がたがたする」などと言われる事がよくあります。
これは、端末エミュレータで基準とされる vt100 や vt220 の仕様が関係しています。

まず、ウィンドウを分割しない状態でのスクロール方法を考えてみます。
vim でスクロールする場合、端末の能力によって幾つかの方法を使い分けたりするのですが、
一番単純な、「最下行にカーソルを移動して改行する」という方法を考えてみます。
今回は端末のサイズを 80x24 として考えます。(以降の例もすべて80x24)
一番単純なスクロール方法を考えると

  1. 最下行にカーソルを移動する -- 7バイト
  2. 改行(CR+LF)を出力する -- 2バイト
  3. カーソルを下から2行目に移動する -- 7バイト
  4. 新しい行の内容を出力する -- 行の内容によるので、とりあえず X バイトとしておく
  5. カーソルを元の位置に移動する -- 6~8バイト

と、だいたい22~24+Xバイトくらいの出力になります。
実際にはもう少し最適化がかかったり、TERMによっては後述のスクロールリージョンが使われたりするので値が変わりますが、大体の目安になります。

次に split コマンドで横分割した場合について考えてみます。
80x24 で split すると、1~11行目が上ウィンドウ、13~22行目が下ウィンドウというように分割されます。
この状況で上ウィンドウをスクロールさせる為に単純にスクロールすると下ウィンドウとして表示した部分まで移動してしまいます。
幸い vt100 にはスクロールする範囲を指定する機能(スクロールリージョン/上下スクロールマージン)があるので、TERM が vt100 や xterm 等の時には vim はこの機能を使います。
例えば上ウィンドウで1行スクロールする場合、

  1. スクロール範囲を1~11行目にする -- 7バイト
  2. カーソルを11行目に移動する -- 7バイト
  3. 改行(CR+LF)を出力する -- 2バイト
  4. スクロール範囲を画面全体(1~24行目)にする -- 7バイト
  5. カーソルを11行目に移動する -- 7バイト
  6. 新しい行の内容を出力する -- X バイト
  7. カーソルを元の位置に移動する -- 6~8バイト

と、だいたい36~38+Xバイトくらいの出力になります。単純に改行してスクロールする場合と比べて14バイト程度の増加ですね。
また、前述したように TERM が vt100, xterm 等の時は非分割時もスクロールリージョンを使ってスクロールするので、実際の増加量は 0 となります。

そして問題の縦分割です。
80x24 で vsplit すると、1~40桁目までが左ウィンドウ、42~80桁目までが右ウィンドウというように分割されます。
縦分割でも単純にスクロールすると関係ないウィンドウの表示位置がずれてしまいますが、vt100 のスクロールリージョンは行単位で指定するため、縦分割では使用できません。
そこでどのようにするかというと、スクロール対象のウィンドウ全体を1行スクロールした状態に書き換えるという事が行われます。

  1. カーソルを1行目1桁目に移動する -- 6バイト
  2. 1行目の内容をスクロールした状態に書き換える -- 40バイト
  3. カーソルを2行目1桁目に移動する -- 6バイト
  4. 2行目の内容をスクロールした状態に書き換える -- 40バイト
  5. カーソルを3行目1桁目に移動する -- 6バイト
  6. 3行目の内容をスクロールした状態に書き換える -- 40バイト
  7. ~略~
  8. カーソルを21行目1桁目に移動する -- 7バイト
  9. 21行目の内容をスクロールした状態に書き換える -- 40バイト
  10. カーソルを22行目1桁目に移動する -- 7バイト
  11. 22行目の内容を空白で埋める -- 40バイト
  12. カーソルを22行目1桁目に移動する -- 7バイト
  13. 新しい行の内容を出力する -- X バイト
  14. カーソルを元の位置に戻す -- 6~8バイト

(40 + 6) * 9 + (40 + 7) * 13 + 7 + 6(~8) + X = 1038~1040+Xバイトと、通常のスクロールに比べて出力が非常に大きくなりました。
カーソル移動に関しては最適化がかかって、例えば左端のウィンドウの場合は CR+LF になったりしますが、画面書き換え部分が大きいので大勢には影響がないでしょう。
この計算では端末のウィンドウサイズを 80x24 と今となっては小さめのサイズで計算していますが、これを例えば自分が普段よく使う 120x84 で計算すると、さらに 4000 バイト程増えます。
また Syntax Hilighting を使っている場合は強調や色付けの出力が増えるのでさらに差が広がります。
縦分割時にスクロールが遅くなるのは、この出力量の違いが大きく影響します。

この問題に対処方法がないのかというと、実はあります。
DEC の vt400 シリーズでは、それまでの行位置でのスクロール範囲の指定の他に、桁位置でのスクロール範囲(左右スクロールマージン)指定が出来るようになりました。
多くの端末エミュレータは vt100 や vt220 の機能を基準に作られていますが、最近では vt400 シリーズ以降の機能をサポートする端末エミュレータも出てきました。
例えば xterm や mlterm, RLogin, tanasinn, pangoterm などが左右スクロールマージンに対応しており、Tera Term でも先日出た 4.79 から対応しています。
これらの端末エミュレータを使っている場合、.vimrc に以下の設定を追加する事によって、縦分割時に左右スクロールマージンを利用してスクロールするようにできます。

let &t_ti .= "\e[?6;69h"
let &t_te .= "\e7\e[?6;69l\e8"
let &t_CV = "\e[%i%p1%d;%p2%ds"
let &t_CS = "y"

この設定を行った状態でスクロールする場合、

  1. スクロール範囲を1~22行目にする -- 7バイト
  2. スクロール範囲を1~40桁目にする -- 7バイト
  3. カーソルを22行目1桁目に移動する -- 7バイト
  4. 改行(CR+LF)を出力する -- 2バイト
  5. スクロール範囲を1~24行目にする -- 7バイト
  6. スクロール範囲を1~80桁目にする -- 7バイト
  7. カーソルを22行目1桁目に移動する -- 7バイト
  8. 新しい行の内容を出力する -- X バイト
  9. カーソルを元の位置に戻す -- 6~8バイト

と、50~52+Xバイトの出力になります。横分割時と比べると14バイト増えていますが、左右スクロールマージンを使わない状態での縦分割から1000バイト近く出力が減っています。
この差は結構大きく、特に途中の回線が遅い時は影響が顕著にでます。
Tera Term での実装中に、シリアル9600bps接続で左右スクロールマージンの利用の有無がどのくらい影響するかを動画に撮ったのですが、これを見ると分かるように大きな効果が出ています。

注意点としては、左右スクロールマージンに非対応の端末でこの設定を行うと、縦分割時のスクロールが正しく表示されなくなります。
この非対応の端末というのには、PuTTY や Gnome Terminal 等の他に GNU Screen や tmux 等のターミナルマルチプレクサも含まれます。
# screen や tmux が非対応なのが地味に痛い
なので使える人は限られますが、対応端末を中心に使っている&vimで縦分割を利用する人は試してみてはどうでしょうか。

*1:
分割線が垂直に入り、ウィンドウが左右に並ぶ状態。
この状態にするのに、vim は vsplit (vertical split) コマンドを使うが、
tmux は split-window -h (horizontal) と縦横が逆になっている。
分割線の入り方を基準にするのか、ウィンドウの並び方を基準にするかの違いだけれど、わかりづらい。

typodupeerror

ナニゲにアレゲなのは、ナニゲなアレゲ -- アレゲ研究家

読み込み中...