2014/12/05 - ssh のコンフィグファイルの条件分岐

この記事は OpenSSH Advent Calendar 2014 (ほとんど俺) の5日目の記事です。 @togakushi さんから受け取りました。

OpenSSH-6.5 で追加された ssh_configMatch についてです。

Match とは

Matchssh のコンフィグファイル( .ssh/config など)で条件分岐をするオプションです。 「特定環境下では追加であのオプションも設定する」というような使い方ができます。

マニュアルを見てみます。

man ssh_config 抜粋:

Match   Restricts the following declarations (up to the next Host or Match keyword) to be used only when the
        conditions following the Match keyword are satisfied.  Match conditions are specified using one or
        more keyword/criteria pairs or the single token all which matches all criteria.  The available key-
        words are: exec, host, originalhost, user, and localuser.

条件に一致した時に、次の Host または Match までのオプションを有効にするようです。

条件

Match で使える条件は以下の5通りです。

キーワード 条件
exec ユーザのシェルでコマンドを実行し、そのステータスコードが0の時
host HostName で指定されている接続先のホスト名
originalhost コマンドラインから入力されたホスト名
user 接続先のログインユーザ名
localuser ssh を実行しているローカルのユーザ名

ホスト名を指定できるものは、 man ssh_config で説明されている パターン が使用できます。

また、exec キーワードはコマンドが実行される前に以下の文字を特定の文字列に変換します。

文字 変換される文字列
%L ローカルのホスト名の最初のドット( . )まで
%l ローカルのホスト名 (ドメイン名がある場合はそれも含む)
%h 接続先のホスト名
%n コマンドラインで指定されたホスト名
%p 接続先のポート番号
%r 接続先のログインユーザ名
%u ssh を実行しているローカルのユーザ名

使い方例

接尾子がついたホスト名でログインしたときはポートフォワードを追加する

config( .ssh/config ):

Host remotehost1 remotehost1-fwd
  HostName 192.168.1.1

Host remotehost2 remotehost2-fwd
  HostName 192.168.1.2

Match originalhost *-fwd
  ExitOnForwardFailure yes
  LocalForward 8080 localhost:80

Host で指定されているホスト名は、 HostName で指定されているアドレスに接続されます。 接尾子として -fwd が付いている場合は、ローカルポートフォワードも追加で設定します。 ポートフォワードを追加するホスト名はパターンを使ってまとめて指定しています。

ログインするユーザ毎に秘密鍵を使い分ける

config( .ssh/config ):

Host remotehost
  Hostname 192.168.1.1

Match user loginuser1
  IdentitiesOnly yes
  IdentityFile .ssh/loginuser1-prvkey

Match user loginuser2
  IdentitiesOnly yes
  IdentityFile .ssh/loginuser2-prvkey

接続するユーザ名によって使用する秘密鍵を使い分けます。

接続している無線APによってプロキシを切り替える

config( .ssh/config ):

# Exclusion list
Match host 192.168.1.1 192.168.1.2
   ProxyCommand none

Match exec "nmcli connection status id 無線AP名1 2> /dev/null"
  ProxyCommand ssh -W %h:%p proxy-server1

Match exec "nmcli connection status id 無線AP名2 2> /dev/null"
  ProxyCommand ssh -W %h:%p proxy-server2

Host remotehost
  User loginuser

nmcli を使って接続中の無線APを判別しています。 exec は、スペースを含むコマンドを実行する場合にクォートで括る必要があります。

exec に指定されているコマンドは ssh が実行されると毎回 すべて 実行されます。 応答が遅いコマンドなどを実行していると、その分だけ接続のレスポンスが悪くなります。

また、一度オプションが有効になると後から無効にできませんので、プロキシを適応したくないホストは先に ProxyCommandnone(使わない) に設定してしまいます。

注意点

1日目 で観察した通り、コンフィグファイルで後から指定するオプションは有効になりません。 つまり、Match を使ってもオプションを 上書きすることはできません 。 「普段使用しているオプションを特定条件下だけ 後から 無効にする/切り替える」という様な使い方はできないので、コンフィグファイルの書き方には注意が必要です。

まとめ

メッチャチョーベンリ。

明日は @togakushi さんです。