Secure Shell のフリーな実装
- MANA-DOT / 2014-07-22: ssh-agentのforwardを利用し、ホストマシンとローカルVMの非公開鍵を共有する
- SSH Examples, Tips & Tunnels, ネタ元: Twitter: 1082289852056461313
- -J、Ubuntu 16.04.04 LTS では 使えないな
C-u すれば良いらしい。
OpenSSH のドキュメントには見当たらない気がする。
READLINE(3) 見ると似たようなキーバーインドはあるけど kill-ring は関係してなさそう。
参考:
OpenSSH のドキュメントには見当たらない気がする。
READLINE(3) 見ると似たようなキーバーインドはあるけど kill-ring は関係してなさそう。
unix-line-discard (C-u) Kill backward from point to the beginning of the line. The killed text is saved on the kill-ring.良くあるキーバーインドに従ってるだけだろうか?
参考:
- リモートの側の sshd_config で X11Forwarding は yes になっているか?
- リモートの側に xauth がインストールされているか?
例えば以下のような環境変数を自動で送っとくと便利である。
設定する箇所は次の通り。
ローカル側の /etc/ssh/ssh_conf に以下の項目がなければ追加
あと Debian で language-env 0.69 使って ~/.bashrc 設定してると
TERM=xterm の時 LANG=C で上書きされてるので以下の箇所を変更しとく必要がある。
- ローカル側と同じロケールで作業したい場合
- LANG LC_*
- X11Forwarding してるときにローカルの漢字変換を使いたい場合
- XMODIFIERS
設定する箇所は次の通り。
ローカル側の /etc/ssh/ssh_conf に以下の項目がなければ追加
SendEnv LANG LC_* SendEnv XMODIFIERSリモート側の /etc/ssh/sshd_conf に以下の項目がなければ追加
AcceptEnv LANG LC_* AcceptEnv XMODIFIERS最後にリモート側の sshd を再起動
あと Debian で language-env 0.69 使って ~/.bashrc 設定してると
TERM=xterm の時 LANG=C で上書きされてるので以下の箇所を変更しとく必要がある。
*** .bashrc~ 2011-02-09 11:01:09.000000000 +0900 --- .bashrc 2011-02-09 11:38:00.000000000 +0900 *************** *** 32,35 **** xterm) if [ "$COLORTERM" != "gnome-terminal" ] ; then ! LANG=C fi ;; --- 32,37 ---- xterm) if [ "$COLORTERM" != "gnome-terminal" ] ; then ! if [ "$LANG" = "" ] ; then ! LANG=C ! fi fi ;;参考:
- watanet Personal Side-C
- spikelet days
セキュリティの向上のため、
最近の known_hosts ファイルには pkey と、一方向 hash 化された hostname の対応が記録さてている。
つまり、hostname から pkey を探すことは出来るが、pkey から hostname を探すことは出来ない。
既に不要な pkey かを判断するためには、以下の方法で hostname から pkey を総当たり的に検索するしかない。
デフォルト port (=22) の場合、hostname をそのまま書く。
デフォルト以外の port (≠22) の場合、[hostname]:port のように書く。
特定のホストに関する鍵の削除は
最近の known_hosts ファイルには pkey と、一方向 hash 化された hostname の対応が記録さてている。
つまり、hostname から pkey を探すことは出来るが、pkey から hostname を探すことは出来ない。
既に不要な pkey かを判断するためには、以下の方法で hostname から pkey を総当たり的に検索するしかない。
ssh-keygen -lF $hostname -f ~/.ssh/known_hostsオプションの意味は以下
- -l : fingerprint で表示(付けなければ、pkey をそのまま表示する)
- -F : 検索する hostname の指定
- -f : known_host ファイルの指定
デフォルト port (=22) の場合、hostname をそのまま書く。
デフォルト以外の port (≠22) の場合、[hostname]:port のように書く。
特定のホストに関する鍵の削除は
ssh-keygen -R "hostname"
known_hosts に記録されていないサーバーへ ssh した場合、以下のように警告が表示される。
各サーバーの pkey をネットワーク越しに調べるには ssh-keyscan コマンドを用いる。
ただし、ネットワーク越しに調べたのでは、なりすましが判別出来ないので、
事前にサーバー上で、サーバー自身の pkey を調べておく必要がある。
つまり、サーバー上で、自分自身の sshd に対して以下のように問合せを行なえば良い。
これは生の pkey なので、fingerprint を調べるには、以下のように ssh-keygen コマンドを通す。
ssh-keygen への pkey 入力がファイル限定(?)なので、上記のように一旦リダイレクトで、ファイルを経由させる必要がある。
名前付きパイプが使えそうなものだが、2011-09-18現在、Debian の openssh-client 1:5.8p1-7 だと、生のファイルじゃないと通らない。
2016-02-12:
OpenSSH 6.8/6.8p1 以降、鍵の fingerprint 生成アルゴリズムが md5 から sha256/base64 に変更になったとの事。
ssh-keygen では -E オプションでこのアルゴリズムを変更出来るらしい。
ssh には fingerprint 生成アルゴリズムの切替機能がないので、
手元に旧 fingerprint の情報しかない場合、一旦 ssh-keygen で新旧対照する必要がある。
簡易的にはこんな感じか?
参考:
$ ssh -p 1234 myserver The authenticity of host '[myserver]:1234 ([127.0.0.1]:1234)' can't be established. RSA key fingerprint is 00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f. Are you sure you want to continue connecting (yes/no)?初回の接続で known_hosts にサーバーが登録されてない場合、サーバーの pkey から計算した fingerprint を事前調べておくことで、安全に ssh で接続できる。
各サーバーの pkey をネットワーク越しに調べるには ssh-keyscan コマンドを用いる。
ただし、ネットワーク越しに調べたのでは、なりすましが判別出来ないので、
事前にサーバー上で、サーバー自身の pkey を調べておく必要がある。
つまり、サーバー上で、自分自身の sshd に対して以下のように問合せを行なえば良い。
ssh-keyscan localhost
これは生の pkey なので、fingerprint を調べるには、以下のように ssh-keygen コマンドを通す。
ssh-keyscan localhost > /tmp/pkey ssh-keygen -vlf /tmp/pkeyssh-keygen のオプションの意味は以下
- -v : verbose. -l オプション使用時に ASCII art 表現も併せて表示させたい場合に付ける。
- -l : fingerprint の計算
- -f : pkey ファイルの指定
ssh-keygen への pkey 入力がファイル限定(?)なので、上記のように一旦リダイレクトで、ファイルを経由させる必要がある。
名前付きパイプが使えそうなものだが、2011-09-18現在、Debian の openssh-client 1:5.8p1-7 だと、生のファイルじゃないと通らない。
2016-02-12:
OpenSSH 6.8/6.8p1 以降、鍵の fingerprint 生成アルゴリズムが md5 から sha256/base64 に変更になったとの事。
ssh-keygen では -E オプションでこのアルゴリズムを変更出来るらしい。
ssh には fingerprint 生成アルゴリズムの切替機能がないので、
手元に旧 fingerprint の情報しかない場合、一旦 ssh-keygen で新旧対照する必要がある。
簡易的にはこんな感じか?
ssh-keycomp () { ( local tmp=$(mktemp -u); trap "rm $tmp" 0; ssh-keyscan "$1" > $tmp; ssh-keygen -E md5 -lf $tmp; ssh-keygen -lf $tmp; ); }
参考:
- Qiita / matokenが / 2012-03-08: ssh鍵の鍵指紋を表示
メンテナンスやテストなどで一時的に立ち上げた ssh サーバーに頻繁に繋いていると、一時的な pkey が known_hosts へ記録されてゴミの山になる。
このように、永続的でない pkey を持つサーバーに接続する場面では、いちいち known_hosts に記録を残したくない。
方法は簡単で -o UserKnownHostsFile オプションを用いて適当に捨て場所を指定してやれば良い。
このように、永続的でない pkey を持つサーバーに接続する場面では、いちいち known_hosts に記録を残したくない。
方法は簡単で -o UserKnownHostsFile オプションを用いて適当に捨て場所を指定してやれば良い。
ssh -o UserKnownHostsFile=/dev/null 192.168.0.1いきなり /dev/null へ捨てるのが不安なら一時ファイル(例えば /tmp/known_hosts 等)に出力しても良いかもしれない。
以下のように -y オプションを用いれば ~/.ssh/id_rsa.pub 相当のものが生成出来るらしい。
ssh-keygen -f ~/.ssh/id_rsa -y参考:
- kanonjiの日記 / 2011-05-14: ssh-keygenで秘密鍵から公開鍵を生成する
base64 encode された鍵を base64 decode して md5sum を取ったものらしい。
以下のようにすると同じ fingerprint が出て来ることを確認出来る。
以下のようにすると同じ fingerprint が出て来ることを確認出来る。
cat ~/.ssh/id_rsa.pub | awk '{print $2;}' | base64 -d | md5sum ssh-keygen -l -f ~/.ssh/id_rsa.pub参考:
- まにっき / 2012-09-11: ssh の RSA 鍵を openssl コマンドで扱ってみる
~/.ssh 以下の SSH キーは
秘密鍵は PEM 形式なので OpenSSL でそのまま使えるのだが、
秘密鍵は OpenSSH の独自形式(?)(RFC4716 形式を1行に展開したような形式) になっているので、
そのままでは OpenSSL で処理出来ない。
このため ssh-keygen -e で PKCS8 形式に export する必要がある。
それぞれの形式に export するには、以下のようにすれば良い。
従って、まず相手に何らかの方法で公開鍵を渡し、その公開鍵で暗号化してもらったものを、こちらで復号化するという使い方になる。
此方から相手に送る際は、何らかの方法で入手した相手の公開鍵で暗号化する必要がある。
公開鍵の受け渡しは、普通は man in middle で改竄されるところまで心配する必要はないはずなのでメールか web で渡せば十分だろう。
どうしても心配なら電話等で fingerprint を確認すればなんとかなるはず。
また、公開鍵暗号である RSA は遅いので、実用的には AES 等の共通鍵暗号で暗号化して、RSA でその共通鍵を暗号化するという使い方になる。
あと rsautl に対応する dsautl, ecutil 等のサブコマンドが見当たらなかったので DSA と ECDSA による encrypt/decrypt する方法は要調査。
pkeyutl は RSA は通るけど DSA と EC はなぜか上手くいない。鍵の作り方が悪いのか???
追記: 2015-03-18
DSA と ECDSA は電子署名の規格なので、公開鍵による暗号化と復号化 (encrypt, decrypt) は出来ない模様。
署名と検証 (sign, verify) は問題なく出来た。
openssl pkeyutl # EC ALGORITHM では sign, verify で ECDSA と derive で ECDH をサポートしているとの事。
以下のようにすると ECDH により同じ値が得られる。
追記: 2015-03-23
ECDSA キーペアと AES256 による暗号化スクリプトを書いてみた。
秘密鍵の機密性について担保出来てさえいるなら、普通はそこまでする必要はない筈だけど。
参考:
秘密鍵は PEM 形式なので OpenSSL でそのまま使えるのだが、
秘密鍵は OpenSSH の独自形式(?)(RFC4716 形式を1行に展開したような形式) になっているので、
そのままでは OpenSSL で処理出来ない。
このため ssh-keygen -e で PKCS8 形式に export する必要がある。
それぞれの形式に export するには、以下のようにすれば良い。
ssh-keygen -f ~/.ssh/id_rsa.pub -e -m PKCS8 > id_rsa.pub.PKCS8 ssh-keygen -f ~/.ssh/id_rsa.pub -e -m PEM > id_rsa.pub.PEM # これは OpenSSL では使えない??? ssh-keygen -f ~/.ssh/id_rsa.pub -e -m RFC4716 > id_rsa.pub.RFC4716 # これは OpenSSL では使えないあとは以下のようにすれば RSA による暗号化と復号化が行える。
openssl rsautl -encrypt -inkey ~/.ssh/id_rsa < file > file.encrypted # RSA 秘密鍵に含まれる公開鍵による暗号化 openssl rsautl -encrypt -inkey id_rsa.pub.PEM -pubin < file > file.encrypted # RSA 公開鍵から PEM 形式で export した公開鍵による暗号化 (pubkey が上手く読めない模様) openssl rsautl -encrypt -inkey id_rsa.pub.PKCS8 -pubin < file > file.encrypted # RSA 公開鍵から PKCS8 形式で export した公開鍵による暗号化 openssl rsautl -decrypt -inkey ~/.ssh/id_rsa < file.encrypted > file.decrypted # RSA 秘密鍵による復号化公開鍵暗号なので、秘密鍵は相手に渡してはいけない。
従って、まず相手に何らかの方法で公開鍵を渡し、その公開鍵で暗号化してもらったものを、こちらで復号化するという使い方になる。
此方から相手に送る際は、何らかの方法で入手した相手の公開鍵で暗号化する必要がある。
公開鍵の受け渡しは、普通は man in middle で改竄されるところまで心配する必要はないはずなのでメールか web で渡せば十分だろう。
どうしても心配なら電話等で fingerprint を確認すればなんとかなるはず。
また、公開鍵暗号である RSA は遅いので、実用的には AES 等の共通鍵暗号で暗号化して、RSA でその共通鍵を暗号化するという使い方になる。
追記: 2015-03-18
DSA と ECDSA は電子署名の規格なので、公開鍵による暗号化と復号化 (encrypt, decrypt) は出来ない模様。
署名と検証 (sign, verify) は問題なく出来た。
openssl pkeyutl # EC ALGORITHM では sign, verify で ECDSA と derive で ECDH をサポートしているとの事。
以下のようにすると ECDH により同じ値が得られる。
openssl pkeyutl -derive -inkey my_ecdsa -peerkey your_ecdsa.pub openssl pkeyutl -derive -inkey your_ecdsa -peerkey my_ecdsa.pub毎回同じ値しか得られないので、どちらか一方が使い捨ての ec ペアを使えば良いのかな?
追記: 2015-03-23
ECDSA キーペアと AES256 による暗号化スクリプトを書いてみた。
- Gist / kou1okada / ec-aes256.sh
秘密鍵の機密性について担保出来てさえいるなら、普通はそこまでする必要はない筈だけど。
参考:
- まにっき / 2012-09-11: ssh の RSA 鍵を openssl コマンドで扱ってみる
- こせきの技術日記 / 2013-02-17: GitHub の公開鍵で暗号化する ghcrypt の処理内容
~/.ssh/config に以下のように並べておくと上の方から順に試されるみたい。
IdentityFile ~/.ssh/id_ecdsa IdentityFile ~/.ssh/id_rsa
パスワード認証したい場合は -o PubkeyAuthentication=no 付けとけば OK
特定の鍵を突っ込みたいときは -i id_seckey 付けとけば OK
ついでに -o PasswordAuthentication=no も付けても良いかも。
特定の鍵を突っ込みたいときは -i id_seckey 付けとけば OK
ついでに -o PasswordAuthentication=no も付けても良いかも。
公開鍵認証する際
~/.ssh/authorized_keys は 644 でも問題ないが
~/.ssh は 700 じゃないと駄目みたい
あと owner にも注意
chmod 700 ~/.ssh のつもりで chown 700 ~/.ssh なんてしてしまい、しばらく頭を抱えてる羽目に陥ったのは内緒だ
~/.ssh/authorized_keys は 644 でも問題ないが
~/.ssh は 700 じゃないと駄目みたい
あと owner にも注意
chmod 700 ~/.ssh のつもりで chown 700 ~/.ssh なんてしてしまい、しばらく頭を抱えてる羽目に陥ったのは内緒だ
~/.ssh/authorized_keys にはいろいろと設定が出来る模様。
1行に全部押し込むのでちょっと可読性に問題があるが、例えばトンネル自動起動用としてパスフレーズを外した秘密鍵に対するペア用の公開鍵なんかをなるべく安全に使いたい場合があったとして、以下のようにすると IP を制限して、さらに cat の入力待ちで何も出来ない状態に出来る。
20190514: 追記
起動時にトンネルを掘って screen 上で維持したいような場合は以下
1行に全部押し込むのでちょっと可読性に問題があるが、例えばトンネル自動起動用としてパスフレーズを外した秘密鍵に対するペア用の公開鍵なんかをなるべく安全に使いたい場合があったとして、以下のようにすると IP を制限して、さらに cat の入力待ちで何も出来ない状態に出来る。
from="192.168.1.xxx/32",command="echo -e \"Tunnel: waiting forever.\nC-D to exit.\";cat" 〜pubkey〜そこから更にサーバー側でローカルに ssh かけてパスワード認証でログイン待ちさせるなら以下のようにしても悪くないだろう。
from="192.168.1.xxx/32",command="echo -e \"Tunnel: waiting forever.\nC-D to exit.\";ssh -oPubkeyAuthentication=no localhost" 〜pubkey〜参考:
- それマグで! / 2011-08-13: authorized_keys ファイルについて調べてみたら楽しかった.
- Ask Ubuntu / 2011-06-10: How to create a restricted SSH user for port forwarding?
- Ubuntu / manual / sshd(8)
20190514: 追記
起動時にトンネルを掘って screen 上で維持したいような場合は以下
多段 ssh で、各段、パスフレーズ省略した共通の鍵で、
踏み台となる 1 段目の remote-1st-host では port forwarding を許可せず、
目的地となる 2 段目の remote-2nd-host では port forwarding を許可する
みたいな設定
local host の ~/.ssh/config
踏み台となる 1 段目の remote-1st-host では port forwarding を許可せず、
目的地となる 2 段目の remote-2nd-host では port forwarding を許可する
みたいな設定
local host の ~/.ssh/config
Host remote-2nd-host ProxyCommand ssh -oIdentityFile=~/.ssh/seckey_for_tunnel remote-1st-host IdentityFile ~/.ssh/seckey_for_tunnel LocalForward localhost:10080 remotehost:80 PermitLocalCommand yes LocalCommand echo "Tunnel is opened."1段目の remote host の ~/.ssh/authorized_keys
command="nc remote-2nd-host 22",no-port-forwarding 〜pubkey_for_tunnel〜2段目の remote host の ~/.ssh/authorized_keys
command="echo -e \"Waiting forever.\nCtrl-D to exit.\"; cat" 〜pubkey_for_tunnel〜
password authentication が有効な環境で ~/.ssh/authorized_keys へ秘密鍵をコピーする場合、
local から以下のようにすれば一発だった。
一方で削除は remote host 上で ~/.ssh/authorized_keys の当該行を削除するしかない模様。
local から以下のようにすれば一発だった。
ssh-copy-id <remote host name>既に登録がある場合、-f オプションで強制的に追加も出来るようだ。
一方で削除は remote host 上で ~/.ssh/authorized_keys の当該行を削除するしかない模様。
X, Y の 2 台のホストがあって、X 経由で Y に転送したいとした場合、~/.ssh/config に以下のように設定しておけばよい。
Host Y ProxyCommand ssh -W %h:%p X
以下のような操作をした場合に terminal が固まってしまう場合がある。
ただし exit しても接続が切れなくって who コマンドで pts を確認しておいて、接続している sshd を kill すると Write failed: Connection reset by peer でようやく接続が切れような状況。
Jambo Frame 対応してもらいたくて ssh server 動いてる Ubuntu Server 側の ifconfig で mtu 16110、ssh client 動いてる Windows 7 の NIC デバイスドライバー詳細設定タブの Jambo Frame で 9KB MTU を設定してたんだけど、これがまずかった模様。
とりあえず freeze した状態で server 側を mtu 1500 にすると、freeze から復帰出来た。
と言うことで、MTU の設定をデフォルトの 1500 にしておくと問題は解決した。
Jambo Frame 対応は、設定詰める必要がありそう。
とりあえず、mtu 16110 の Ubuntu Server 13.04 と 9KB MTU の Windows 7 だと頻繁に発生。
mtu 16110 の Ubuntu Server 13.04 と mtu 6128 の Ubuntu Desktop 12.04 LTS だと今のところこの不具合は確認出来てない。
参考:
- ある程度行数あるファイルを cat する
- ある程度のファイル数のあるディレクトリを ls -l する
- lv や byobu 等 ncurses 使ってるコマンドで画面をスクロールする
ただし exit しても接続が切れなくって who コマンドで pts を確認しておいて、接続している sshd を kill すると Write failed: Connection reset by peer でようやく接続が切れような状況。
Jambo Frame 対応してもらいたくて ssh server 動いてる Ubuntu Server 側の ifconfig で mtu 16110、ssh client 動いてる Windows 7 の NIC デバイスドライバー詳細設定タブの Jambo Frame で 9KB MTU を設定してたんだけど、これがまずかった模様。
とりあえず freeze した状態で server 側を mtu 1500 にすると、freeze から復帰出来た。
と言うことで、MTU の設定をデフォルトの 1500 にしておくと問題は解決した。
Jambo Frame 対応は、設定詰める必要がありそう。
とりあえず、mtu 16110 の Ubuntu Server 13.04 と 9KB MTU の Windows 7 だと頻繁に発生。
mtu 16110 の Ubuntu Server 13.04 と mtu 6128 の Ubuntu Desktop 12.04 LTS だと今のところこの不具合は確認出来てない。
参考:
OpenSSH 7.0 では脆弱性対策のため DSA(ssh-dss) がデフォルトでは無効にされたらしい。
この結果、接続先のサーバーが古いと以下のようなエラーで接続出来ない場合がある。
参考:
追記: 2016-07-04
言うまでもないが、~/.ssh/config に設定しなくても ssh に以下のオプションを与えても良い。
この結果、接続先のサーバーが古いと以下のようなエラーで接続出来ない場合がある。
Unable to negotiate with xxx.xxx.xxx.xxx: no matching host key type found. Their offer: ssh-dssセキュリティ的にはサーバーをバージョンアップするのが筋だが、サーバーが自分の管理下になくて対応してもらえないような場合、仕方がないので ~/.ssh/config に以下の様な設定を追加しておくと ssh-dss を有効に出来る模様。
servername HostKeyAlgorithms ssh-dssCygwin が Linux や BSD よりも先行して OpenSSH の新しいバージョン入れてたりするので、特に Cygwin から古いサーバーに接続する際に問題が出易い。
参考:
- Tizen には moe ていない blog / 2015-09-23: GitbucketのSSHにmsys2のsshから接続に行ったらエラーになった
追記: 2016-07-04
言うまでもないが、~/.ssh/config に設定しなくても ssh に以下のオプションを与えても良い。
-o HostKeyAlgorithms=ssh-dss
タグ
コメントをかく