Zsh
SSH
Peco

私の考えたzsh最強のssh接続設定

※ 基本zshで検証してます。print -z 等適宜読み替えてください。
ソースだけ欲しい人は一番下へどうぞ。
適宜追記する予定。

追記内容

  • 2016-07-04 @iwaim@github さんの指摘内容を追記。秘密鍵の管理について

目次

やりたいこと、たくさんありますよね。
目次でも書きましょうか。

  • ssh_configをconf.d/のようにファイル分割したい
  • ~/.ssh/以下をgit管理したい
  • peco でssh接続先を探せるようにしたい

ssh_configをconf.d/のようにファイル分割する

みんな考えることは大体同じよね。
http://qiita.com/tukiyo3/items/6afb1e9c8e2ca411bc47
http://qiita.com/passol78/items/2ad123e39efeb1a5286b

とりあえず、私なりの考え。
安全策をこれでもかと盛り込んでみた。

.zshrc
# conf.dがないときは使わない。安全装置の意味も込めて。
if [ -d ~/.ssh/conf.d ]; then
  # こちらも安全装置の意味も込めて、初回はバックアップを作成
  if [ -f ~/.ssh/config ]; then
    test -f ~/.ssh/config.bk || cp ~/.ssh/config ~/.ssh/config.bk
  fi
  # git関連のディレクトリは除外してconfigファイルを生成する ※後述
  alias ssh-config-update=": > ~/.ssh/config && echo '# DO NOT EDIT! Please edit conf.d/' >> ~/.ssh/config && find ~/.ssh/conf.d -type f | grep -v '/\.git' | xargs cat >> ~/.ssh/config;"
  alias ssh="ssh-config-update; ssh"
fi

追記 2017-07-28

openssh 7.3 あたりから Include ディレクティブが使えるようになった。

http://qiita.com/masa0x80/items/ecb692ad93f7d06a07b0

~/.ssh/config
Include ~/.ssh/conf.d/**/*.conf

と書いておけば良い。

~/.ssh/以下をgit管理したい

現在、4台のMacを運用中。それぞれでgit管理したい。なるべく楽で、なるべくセキュアに。

2016-07-04追記: @iwaim@github 秘密鍵(private key)の管理は慎重に。念を入れたいならばネットワーク上ではなく、暗号化したUSBメモリ等において安全な場所で管理すること。

ファイルごとの安全重要度

それぞれ、ファイルの重要度が異なることに注目。
最もスタンダードだと~/.ssh/は以下の様なファイルが入っているはず。

~/.ssh/以下の構造
config          # ssh接続設定(ssh_config)
id_rsa          # 秘密鍵
id_rsa.pub      # 公開鍵
known_hosts     # 接続済みホスト情報
authorized_keys # 公開鍵登録情報

このファイルたちをポイント1P〜3Pで評価してみる。
※ 数字が大きいほど重要。

  • 1PはGithub Public リポジトリでも良い。
  • 2PはGithub Private リポジトリが良い。
  • 3Pは安全なネットワーク上(自宅LAN)にあるgitlab等のリポジトリが良い。
    ※ 外部からはアクセス出来ない場所でストレージは暗号化されていると良い。

config(2P)

重要度は比較的中くらい。sshの接続設定。
ホスト名が入ってる。パスワードは入っていないため、
踏み台等を使っている場合は、踏み台先がバレる等があるため、なるべくなら人の目に触れないようにしたい。

id_rsa(3P)

最も重要。秘密鍵。
流出は絶対に避けなければならない。

id_rsa.pub(1P)

重要度は低い。公開鍵。
流出しても痛くはないし、人に気軽に渡すものなんでgithubに上げても良いぐらい。
と思っていたら、github apiで取得出来ていた模様。現在は不明。

known_hosts(2P)

重要度は低い。接続済みホスト情報。
書き換えられると攻撃に利用されるおそれがあるが、流出は特に問題はない。
そもそも、共有する必要すらないのでgitignoreする。

authorized_keys(1P?)

重要度は低い。多分。公開鍵登録情報。
これも書き換えられると困る。流出する分にはあまり問題ないけれど、サーバーに設定されている公開鍵がバレるので、大々的に公開はしないほうが良い。
sshクライアント側(Mac)には、基本的に設定しないのであまり書きません。

重要度を考え、git リポジトリ構成を作ってみる

~/.ssh以下
.
├── .gitignore
├── conf.d
│   ├── group1
│   └── group2
├── config
├── id_rsa -> keys/private/id_rsa
├── id_rsa.pub -> keys/public/id_rsa.pub
├── keys
│   ├── private    # 秘密鍵を保管
│   │   └── id_rsa
│   └── public     # 公開鍵を保管
│       └── id_rsa.pub
└── known_hosts

git submodule を利用して、重要度3Pを管理する

基本はgithub privateリポジトリで管理をすれば良い。
しかし、重要度3Pは誰でも見えるインターネット上に置きたくない。
そんなとき、git submodule機能を利用すれば実現可能。

/keys/private を別リポジトリとし、自宅のgitlabにリポジトリを設置すれば良い。

.gitignoreの構成

.gitignore
/id_rsa
/id_rsa.pub
/known_hosts
/config
/config.bk

.DS_Store

これでおk!
※ conf.dの機能を使わない場合は/configをリポジトリ管理したほうが良い。

peco でssh接続先を検索できるようにする

簡単。

pecoで探す
alias ssh-peco='ssh-config-update; print -z ssh $(cat ~/.ssh/config | grep '^Host" | sed -e "s;Host *;;g" | peco | awk "{print $1}")'

ソースだけ

ソース
# ssh_configをconf.d/へファイル分割する機能
if [ -d ~/.ssh/conf.d ]; then
  if [ -f ~/.ssh/config ]; then
    test -f ~/.ssh/config.bk || cp ~/.ssh/config ~/.ssh/config.bk
  fi
  alias ssh-config-update=": > ~/.ssh/config && echo '# DO NOT EDIT! Please edit conf.d/' >> ~/.ssh/config && find ~/.ssh/conf.d -type f | grep -v '/\.git' | xargs cat >> ~/.ssh/config;"
  alias ssh="ssh-config-update; ssh"
fi

# pecoでssh接続先を探す
alias ssh-peco='ssh-config-update; print -z ssh $(cat ~/.ssh/config | grep '^Host" | sed -e "s;Host *;;g" | peco | awk "{print $1}")'

終わりに

今まで散らかったままだったけど、今回整備してみて快適になった。
課題としては、秘密鍵の管理。そう頻繁に更新するものでもないので、バージョン管理の必要はないかなと。
秘密鍵ファイルをtarで固めてopensslコマンドでガッチガチに暗号化し、暗号化ファイルをDropbox、パスフレーズをGoogleDrive等に置いておくのも手かもしれない。