NSAが兆単位の通信を盗聴してるよって話とその対策(ssh編)

# はじめに

先日Hacker Newsで「NSAが兆単位の暗号化された通信を盗聴してる」みたいな[記事](http://thehackernews.com/2015/10/nsa-crack-encryption.html)を見かけました。
1024ビットのDHキーを1つ突破するためには時間で1年、お金だと数百万ドルのコストがかかるけど、暗号で使われる素数は同じものが多く使われているらしいので、年110億ドルの予算では兆単位の接続を盗聴できてるんじゃないかといった話でした。
全然気にしてなかったんですが、[元サイト](https://freedom-to-tinker.com/blog/haldermanheninger/how-is-nsa-breaking-so-much-crypto/)で公開されてた[論文](https://weakdh.org/imperfect-forward-secrecy-ccs15.pdf)を見てみたら(読んだとは言えないレベルｗ)対策自体は簡単だったのでまとめです。

ssh編と書いたとおりssh接続での対策です。sshのフェーズの中での鍵交換の話です。
需要がありそうだったらWebServer編も書くかもしれませんが、Logjam対策してれば大体OKな内容なので多分イラナイと思ってます。
あと、Mozillaの[このページ](https://wiki.mozilla.org/Security/Server_Side_TLS)がとても参考になると思います。

# 対策

引っ張っといてアレなんですが、対策は凄く簡単です。てか、最近のOSなら多分不要な気がしてきたので、このポストいらなくね？って思い始めて来ましたｗ

でもとりあえず進めます。

元論文の5. Recommendationを見る限り、まずDHじゃなくて適切なパラメータでECDH(Elliptic Curve Diffie Hellman:楕円曲線DH)にすればオールオッケーらしいです。それができないなら2048ビット以上のDHを使いましょうってことらしいです。それもできないならよく使われてるような1024ビットの素数じゃなくて別の素数を使いましょうってことらしいですが、今の時代にインターネットを通して接続するsshで1024ビットを使わなきゃいけないってことはアリエナイと思うのでこれは気にしなくて良いと思われます。

具体的な対策としてはサーバ側の/etc/ssh/sshd_configとクライアント側の/etc/ssh/ssh_configで上記のOKなアルゴリズムのみ使うようにすればOKです。

手元の環境(Fedora22)で見るといずれもデフォルトではエントリーがなかったのでmanを確認すると以下のようになってました。

```bash:sshd_configのmanページの該当箇所
     KexAlgorithms
             Specifies the available KEX (Key Exchange) algorithms.  Multiple algorithms must be comma-separated.  The supported algorithms are:

                   curve25519-sha256@libssh.org
                   diffie-hellman-group1-sha1
                   diffie-hellman-group14-sha1
                   diffie-hellman-group-exchange-sha1
                   diffie-hellman-group-exchange-sha256
                   ecdh-sha2-nistp256
                   ecdh-sha2-nistp384
                   ecdh-sha2-nistp521

             The default is:

                   curve25519-sha256@libssh.org,
                   ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
                   diffie-hellman-group-exchange-sha256,
                   diffie-hellman-group14-sha1

             The list of available key exchange algorithms may also be obtained using the -Q option of ssh(1) with an argument of “kex”.
```

```bash:ssh_configのmanの該当箇所
     KexAlgorithms
             Specifies the available KEX (Key Exchange) algorithms.  Multiple algorithms must be comma-separated.  The default is:

                   curve25519-sha256@libssh.org,
                   ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
                   diffie-hellman-group-exchange-sha256,
                   diffie-hellman-group-exchange-sha1,
                   diffie-hellman-group14-sha1,
                   diffie-hellman-group1-sha1

             The list of available key exchange algorithms may also be obtained using the -Q option of ssh(1) with an argument of “kex”.
```

sshd側のデフォルトは`curve25519-sha256@libssh.org, ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, diffie-hellman-group-exchange-sha256, diffie-hellman-group14-sha1`、ssh側のデフォルトは`curve25519-sha256@libssh.org, ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, diffie-hellman-group-exchange-sha256, diffie-hellman-group-exchange-sha1, diffie-hellman-group14-sha1, diffie-hellman-group1-sha1`でした。
ちなみにsshではサーバ側とクライアント側で一番最初にマッチしたのが使われます。なので、この場合は両者でサポートされている`curve25519-sha256@libssh.org`が使われます。これは論文でOKな例として挙げられているものです。。。てことで危惧した通り何もやらなくてOKでしたって結論になってしまいましたｗ

が、サーバとしてもクライアントとしても別の端末から/へのアクセスがあるかもしれないので、有効になっているものを調べてみます。

ecdhが付いているものはOKなのでそれ以外を当たると、まずサーバ側はdiffie-hellman-group-exchange-sha256とdiffie-hellman-group14-sha1が使われる可能性があります。diffie-hellman-group-exchange-sha256は[ここ](https://www.ietf.org/rfc/rfc4419.txt)によるとサーバ側がサイズを選択するようなので無効にしておいた方が良さそうです。diffie-hellman-group14-sha1は[ここ](https://tools.ietf.org/html/rfc4253)によると2048ビットなので大丈夫そうです。

次にクライアント側はサーバ側のものに追加でdiffie-hellman-group-exchange-sha1とdiffie-hellman-group1-sha1が入ってます。
diffie-hellman-group-exchange-sha1はdiffie-hellman-group-exchange-sha256と同様にサーバ側でサイズを選択するので無効にしておいた方が良さそうです。diffie-hellman-group1-sha1は[ここ](https://tools.ietf.org/html/rfc4253)によると1024ビットなので無効にしておいた方が良さそうです。

ということで、それぞれを無効にするにはsshd_configとssh_configそれぞれに設定します。

自分の場合はサーバ側は自分が把握しているクライアントしか繋がないので素のdhは無効にしてecdhのみとして以下のようにしました。

```bash:sshd_config
KexAlgorithms  curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521
```

一方クライアント側は他にも接続する可能性があるので安全じゃないものだけ削除して、以下のようにしました。

```bash:ssh_config
KexAlgorithms  curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group14-sha1
```

なお、OpenSSHの場合はサーバ側でサイズを選択する際に見るファイルは/etc/ssh/moduliに書かれています。
こんな感じの値が並んでいます。

```bash:/etc/ssh/moduli
20150520234251 2 6 100 1535 2 A0F3BD(略)
```

左から5番目の数字がサイズ(上記の例では1535)なので、2047より小さいものは全て削除またはコメントアウトするという対策でも良さそうです。

sshdの再起動も忘れずに。


# 最後に

以上。
おかしな点があったらツッコミください。