私の考えた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

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

```zsh:.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/`は以下の様なファイルが入っているはず。

```bash:~/.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で取得出来ていた模様。現在は不明。](http://www.slideshare.net/hnw/edomaesec-20150124)

#### known_hosts(2P)

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

#### authorized_keys(1P?)

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

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

```shell:~/.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の構成

```bash:.gitignore
/id_rsa
/id_rsa.pub
/known_hosts
/config
/config.bk

.DS_Store
```

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

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

簡単。

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



## ソースだけ

```zsh:ソース
# 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等に置いておくのも手かもしれない。