さて、OpenSSH の動きがわかったところで、
この章では実際に sshd
サーバデーモンが動いているマシンに
遠隔地のクライアントからログインする方法をご説明しましょう。
ここではまずクライアントもサーバも両方 UNIX マシンであり、 それぞれ OpenSSH クライアントとサーバがインストールされ、 サーバデーモンが正しく動いていると仮定しています。 Windows や Mac OS X からクライアントを使う方法については 4.6. UNIX 以外のマシンからログインする で紹介します。 なお、OpenSSH では異なる新旧 2つの SSH プロトコル (SSH1 プロトコル と SSH2 プロトコル) がサポートされており、 これらはコマンドの機能や公開鍵の形式がやや異なっています。 最近では新しい方の SSH2 プロトコルが普及しているため、この章では SSH2 プロトコルのみを扱います。 古い SSH1 プロトコルとの相互運用については 6.7.1. SSH1 プロトコルを使う を参照してください。
公開鍵認証を使ってログインする場合、ユーザの手順は次のようになります:
1. と 3. の項では、ユーザはクライアントの上で作業します。 2. の項では、ユーザはサーバに直接 (ネットワーク経由ではなく) ログインするか、 あるいは公開鍵をサーバの管理者に送って登録してもらうよう依頼する必要があります。
4.1.2. 公開鍵をサーバに登録する では、クライアントユーザがサーバに直接ログインして作業することを前提とします。
はじめにクライアント上で秘密鍵と公開鍵ペアを生成しましょう。
OpenSSH には鍵のペアを生成する ssh-keygen
というプログラムが含まれています。
これを以下のように実行します。
秘密鍵と公開鍵ペアを生成する |
---|
$ ssh-keygen -t rsa |
実行例:
client$ ssh-keygen -t rsa (RSA方式の鍵を生成する) Generating public/private rsa key pair. Enter file in which to save the key (/home/yusuke/.ssh/id_rsa): (パス名を入力、あるいは Enter を押す) Created directory '/home/yusuke/.ssh'. (ディレクトリ ~/.ssh/ が作成される) Enter passphrase (empty for no passphrase): (秘密鍵につけるパスフレーズを入力する) Enter same passphrase again: (同じパスフレーズをもう一度入力する) Your identification has been saved in /home/yusuke/.ssh/id_rsa. (鍵が生成された) Your public key has been saved in /home/yusuke/.ssh/id_rsa.pub. The key fingerprint is: 23:56:6e:90:f3:98:fc:7b:2a:92:fb:46:bf:20:98:71 yusuke@client (公開鍵の指紋が表示される)
ここで使用した -t rsa
というオプションは
RSA 方式の鍵を生成するよう指示するものです。
OpenSSH の公開鍵認証で使える鍵には RSA と DSA という 2種類の方式があります。
どちらの鍵を使ってもそれほど差はないと考えられていますので、
ここではデフォルトの RSA 方式を使います。
バージョン 4.3p1 以降の OpenSSH では、-t rsa
を指定しなくても
自動的に RSA 方式の鍵が生成されます。
[脚注: DSA 方式は、もともと RSA 方式に特許がまだ有効だったころ、
その特許を回避するために開発されたものです]
ssh-keygen
は秘密鍵と公開鍵のペアを生成したあと、
それらをユーザのホームディレクトリ ~/.ssh/
に保存します (図 generate-pubkey-pair)。
このディレクトリが存在していない場合は自動的に作られます。
秘密鍵を格納したファイルは安全のためにそれ自体が暗号化されており、
ここで入力したパスフレーズはあとでそれを使用するときに使われます。
3.3.2. 秘密鍵・公開鍵ペアを使ったユーザ認証 で説明したとおり、このパスフレーズはネットワーク上には流れません。
ssh-keygen
の実行後、ユーザの ~/.ssh/
ディレクトリは次のようになっているはずです:
client$ ls -la ~/.ssh/ (~/.ssh/ ディレクトリの内容を表示する) drwx------ 2 yusuke users 104 Mar 9 07:13 ./ drwxr-xr-x 60 yusuke users 4048 Mar 9 07:13 ../ -rw------- 1 yusuke users 1675 Mar 9 07:12 id_rsa (秘密鍵を格納したファイル) -rw-r--r-- 1 yusuke users 394 Mar 9 07:12 id_rsa.pub (公開鍵を格納したファイル)
ここで、~/.ssh/
ディレクトリのパーミッションと、秘密鍵を記録した id_rsa
ファイルの
パーミッションがそれぞれ 700 (-rwx------
、所有者のみが読み書き実行可能) と
600 (-rw-------
、所有者のみが読み書き可能) になっていることに注意してください。
秘密鍵ファイルが他人から読める状態になっていると、OpenSSH クライアントはその使用を拒否します。
生成された id_rsa
ファイルと id_rsa.pub
ファイルはどちらも
テキストファイルであり、その内容は以下のようになっています。
[脚注: なお id_rsa.pub
ファイルはただ 1行のテキストファイルですが、
1行が非常に長いため、実際の端末上では何行にも分かれて見えます。]
id_rsa
ファイル:
client$ cat ~/.ssh/id_rsa -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,3DF819517CEB371F 7t1IOZJdKwjVuJiUVx5WglDWbnLD9B4HB/I1etwlqFSdrweyU+V3h+xbxfEvdBQc dXKcK0j4enTMzhBrUOjGJxS0b1TNG06O3HiLsjuTLGzm1fjmJkbDC68WkA/Nz+Si ... 0g7kSz64iYACKFXrIiuD5dNPVUhJegS37iOcPl/2h7VK6QsDzOK95g== -----END RSA PRIVATE KEY-----
id_rsa.pub
ファイル:
client$ cat ~/.ssh/id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAoIiNSHbpbrpMGTE7Dv...(中略)...r85xe/RC6WidsmebTYlZC91Lmw== yusuke@client
これ以降、この id_rsa
ファイルを、クライアントの外部に持ちだす必要は決してありません。
いっぽう、公開鍵の入った id_rsa.pub
ファイルは、この後サーバに登録するため、
サーバに転送する必要があります。秘密鍵のサーバへの登録方法については 4.1.2. 公開鍵をサーバに登録する で説明します。
なお、秘密鍵につけたパスフレーズを変更するには、次のようにします:
秘密鍵のパスフレーズを変更する |
---|
$ ssh-keygen -p [-f 秘密鍵ファイル] |
実行例:
client$ ssh-keygen -p Enter file in which the key is (/home/yusuke/.ssh/id_rsa): (秘密鍵ファイルの位置を入力する、デフォルトなら Enter) Enter old passphrase: (古いパスフレーズを入力する) Key has comment '/home/yusuke/.ssh/id_rsa' (秘密鍵ファイルのコメントが表示される) Enter new passphrase (empty for no passphrase): (新しいパスフレーズを入力する) Enter same passphrase again: (新しいパスフレーズをもう一度入力する) Your identification has been saved with the new passphrase. (秘密鍵ファイルが更新された)
秘密鍵と公開鍵のペアを生成したら、
サーバに公開鍵ファイル id_rsa.pub
を転送し、登録します。
登録はクライアントユーザの (サーバ上にある) ホームディレクトリ以下の
~/.ssh/authorized_keys
と呼ばれるファイルに
id_rsa.pub
の内容を追記することによっておこないます (図 send-pubkey-to-server)。
id_rsa.pub
と同様に
~/.ssh/authorized_keys
ファイルもまたテキストファイルで、
そこには 1行につきひとつの公開鍵が格納されています。
混乱しやすいですが、クライアントにもサーバにも
~/.ssh/
ディレクトリが必要なことに注意してください:
クライアント側の ~/.ssh/ |
サーバ側の ~/.ssh/ |
---|---|
ログインに使う秘密鍵ファイル (id_rsa あるいは id_dsa ) が必要。
client$ ls -la ~/.ssh/ drwx------ 2 yusuke users 104 Mar 9 07:13 ./ drwxr-xr-x 60 yusuke users 4048 Mar 9 07:13 ../ -rw------- 1 yusuke users 1675 Mar 9 07:12 id_rsa -rw-r--r-- 1 yusuke users 394 Mar 9 07:12 id_rsa.pub |
ログインに使う秘密鍵に対応する公開鍵 (id_rsa.pub または id_dsa.pub ) を
登録した authorized_keys ファイルが必要。
server$ ls -la ~/.ssh/ drwx------ 2 yusuke users 104 Mar 9 12:11 ./ drwxr-xr-x 59 yusuke users 4136 Mar 9 14:02 ../ -rw------- 1 yusuke users 1586 Mar 9 18:01 authorized_keys ※ これはサーバ上のユーザー yusuke が直接コマンドを実行した場合の出力例です。 |
id_rsa.pub
ファイルの転送方法はどのようなものでもかまいませんが、
できるだけ信頼できる方法を使う必要があります。
なぜなら公開鍵は重要な情報であり、これが転送中に
別のものにすり替えられてしまうと、本来意図したユーザとは
別のユーザのログインが可能になってしまうからです。
別のユーザのログインを認めてしまうことになるからです。
[脚注: とはいうものの、筆者は実際のところ公開鍵の転送に電子メールを使っています。]
このとき、id_rsa.pub
がすり替えられていないかどうかを確かめるには、
ssh-keygen
コマンドを使って公開鍵の指紋を確認します。
公開鍵の指紋を確認する |
---|
$ ssh-keygen -l [-f 公開鍵ファイル] |
実行例:
server$ ssh-keygen -l -f id_rsa.pub 2048 23:56:6e:90:f3:98:fc:7b:2a:92:fb:46:bf:20:98:71 id_rsa.pub (鍵の長さと指紋が表示される)
注意 |
---|
公開鍵が同じかどうか確認するときは、
id_rsa.pub ファイルの内容を目で比べることはせず、
かならず指紋を照合するようにしてください。
id_rsa.pub ファイルの最初の数十文字はどの公開鍵でも共通です。
|
さて、サーバへ無事に id_rsa.pub
を転送できたと仮定します。
このあと (サーバ上の) ホームディレクトリ以下にも同じ ~/.ssh/
ディレクトリを作成し、以下のようにして id_rsa.pub
ファイルの内容を
~/.ssh/authorized_keys
ファイルに追加します:
server$ mkdir ~/.ssh/ (.ssh ディレクトリを作成する) server$ cat id_rsa.pub >> ~/.ssh/authorized_keys (id_rsa.pub の内容を authorized_keys に追加する)
ここで cp
ではなく cat
を使っているのは、
~/.ssh/authorized_keys
ファイルを上書きするのではなく、
id_rsa.pub
の内容をこのファイルに追加しているからです。
authorized_keys
ファイルには、以下のように
複数の公開鍵を登録することができます:
$ cat ~/.ssh/authorized_keys ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAoIiNSHbpbrpMGTE7Dv...(中略)...r85xe/RC6WidsmebTYlZC91Lmw== yusuke@client (公開鍵1) ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6H91zpdy0pXubJgEV2...(中略)...pR5ehR6hIS5BzdIF3rwjQZhI+Q== yusuke@laptop (公開鍵2)
このような場合、新しい公開鍵を登録するときに
他の公開鍵を消してしまわないよう、公開鍵の登録には cp
ではなく
cat
を使うくせをつけておくとよいでしょう。
ではログインしてみましょう。
公開鍵認証では、サーバはクライアントが持っている秘密鍵のうち、
それに対応する公開鍵が ~/.ssh/authorized_keys
ファイル中に
登録されているかどうかを調べます。対応する公開鍵があった場合、サーバは
公開鍵暗号技術をもちいてクライアントに秘密鍵の所有を証明するよう要求します。このときクライアントは
id_rsa
ファイル中に格納されている暗号化された秘密鍵を復元するために、
ユーザにパスフレーズの入力を促します。正しいパスフレーズが与えられると秘密鍵が復元され、
秘密鍵の所有がサーバに証明されることで、ログインが成功します (図 pubkey-authentication-in-real)。
[脚注: 厳密には、クライアントはまず自分の持っている秘密鍵に対応する
公開鍵をサーバに送ります。その公開鍵がサーバに登録されている場合、
サーバはある秘密の値をその鍵によって暗号化してクライアントに送ります。
公開鍵によって暗号化された情報を正しく復号するにはそれに対応する
秘密鍵が必要なため、もしクライアントがその値を正しく復号して
送り返してくれば、そのクライアントは対応する秘密鍵をもっていると確信できます。]
ssh コマンドでログインするには、以下のように入力します。
サーバ上でも同じユーザ名を使っている場合は、"ユーザ名@
" の
部分を省略してもかまいません。なお、デフォルトでは ssh
は
リモートホストの TCP 22番ポートに接続しますが、サーバ側の sshd
のポート番号を
変えている場合 (5.5.3. パスワード推測攻撃を避ける 参照) は -p
オプションでポート番号を
指定する必要があります。
ログインする |
---|
$ ssh [-p ポート番号] [ユーザ名@]ホスト名 |
なお、秘密鍵ファイルが ~/.ssh/id_rsa
あるいは ~/.ssh/id_dsa
以外である場合は、
以下のように -i
オプションを使って秘密鍵ファイルをじかに指定することもできます。
特定の秘密鍵ファイルをつかってログインする |
---|
$ ssh [-p ポート番号] [-i 秘密鍵ファイル] [ユーザ名@]ホスト名 |
すると、おそらく次のように表示されるでしょう。
client$ ssh yusuke@server.example.com The authenticity of host 'server.example.com (11.22.33.44)' can't be established. RSA key fingerprint is ac:62:6e:32:7e:6f:bc:6a:2f:a1:e5:f3:a5:db:7f:c0. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added server.example.com,11.22.33.44' (RSA) to the list of known hosts. Enter passphrase for key '/home/yusuke/.ssh/id_rsa': (秘密鍵のパスフレーズを入力する) Last login: Mon Mar 13 12:01:22 2006 from xx.xx.xx.xx server$
3.2. ホスト認証のしくみ で説明したように、そのサーバにはじめてログインしたときは
そのサーバのホスト公開鍵の指紋が表示されます。ユーザはその指紋が正しいかどうかを確認し、
正しければ yes
を入力します。一度この確認をしたあとは
server.example.com
のホスト公開鍵は ~/.ssh/known_hosts
ファイルに記録されるため、
2回目以降のログインではこの質問はされなくなります。
注意 |
---|
あるサーバに接続したとき、OpenSSH はそのサーバに対応するホスト公開鍵を
known_hosts ファイルの中から検索しますが、ここでのホスト名は
ssh コマンドに渡された名前がそのまま使われます。
したがって、たとえ server.example.com と
mail.example.com が同じ IPアドレスを指していたとしても、
OpenSSH はこの事実を考慮せず、正確にその名前で登録されているホスト公開鍵を検索します。
これは DNS 詐称によるなりすましを防ぐためです。
もし指定されたホスト名をいったん IPアドレスに変換してから保存したとすれば、
悪意ある DNS サーバがそのホスト名に別の IPアドレスを割り当てることで、
ホスト公開鍵の検証を回避できてしまうためです。
このため、たとえ同じ IP アドレスを指すホスト名でも、これまでに
ssh コマンドの引数として使われたことがなければ OpenSSH は
ホスト公開鍵の確認を求めます。また、 DNS 詐称を検出するために OpenSSH では
ホスト名とそれに対応する IPアドレスもあわせて
known_hosts ファイル内に保存しています。
|
client$ cat ~/.ssh/known_hosts (known_hosts ファイルの内容を確認する) server.example.com,11.22.33.44 ssh-rsa AAAAB3NzaC1yc2E...(中略)...NVdw1Nrs= (server.example.com と 11.22.33.44 のホスト公開鍵が登録されている) client$ ssh yusuke@server.example.com (2回目のログイン) Enter passphrase for key '/home/yusuke/.ssh/id_rsa': (秘密鍵のパスフレーズを入力する) Last login: Mon Mar 14 15:12:43 2006 from xx.xx.xx.xx server$
ここでユーザが入力したパスフレーズはサーバには送信されず、
クライアント上で暗号化された秘密鍵を復元するためだけに使われています。
秘密鍵はふだんは id_rsa
ファイルの中に暗号化されて保存していますが、
ユーザからパスフレーズを与えられると復元して使用できる状態になります。
この秘密鍵自身はサーバに送信されないので、
ユーザは秘密の情報をいっさいネットワーク上に流さずに
サーバに安全にログインすることができたわけです。
サーバに対話的にログインしている時は、
エスケープシーケンス (escape sequence) が使用できます。
これは ~
(チルダ文字) で始まる特定の文字をタイプすることによって、
現在の ssh
クライアントの状態を制御できる機能です。
代表的なエスケープシーケンスを表 ssh-escape-sequences に示しました。
なお、エスケープシーケンス機能が利用できるのはサーバ上に仮想端末が割り当てられているときのみであり、
リモートコマンド (4.1.4. リモートコマンドを実行する 参照) を実行するさいにはエスケープシーケンス機能は利用できません。
入力する文字列 | 効果 |
---|---|
~. |
現在の接続を強制的に切断する。 |
~^Z (Control-Z) |
ssh をバックグラウンド化する。 |
~& |
X11 転送を有効にしている場合、シェルを抜けた後に ssh をバックグラウンド化する。 |
~# |
現在有効になっているポート接続の一覧を表示する。 |
~? |
エスケープシーケンスのヘルプ画面を表示する。 |
~C |
コマンドラインに入る。ポート転送を追加・停止したり、ローカルホスト上でコマンドを実行できる。 |
~~ |
実際のチルダ文字 (~~) を入力する。 |
OpenSSH では、ログインして対話的なシェルを実行するかわりに
リモートホスト (サーバ) 上で特定のコマンドを一回だけ実行し、
すぐにログアウトするという機能もあります。この場合、
ssh
コマンドは与えられた引数をコマンド列として
sshd
に渡し、sshd
は
サーバ上でこのコマンド (リモートコマンド) を実行します。
このとき ssh
への標準入力がサーバ上で実行されるプロセスの標準入力に転送され、
このプロセスの標準出力が ssh
の標準出力に転送されます (図 remote-command)。
また、サーバ上のプロセスの終了状態もそのままクライアント上に転送され、ssh
コマンドの
終了状態となるので、この機能を使うことにより遠隔地のマシンのコマンドをあたかも
ローカルにあるかのように実行できます。この仕組みは、分散処理システムなどで使われる
RPC (リモートプロシージャコール) に似ています。
なお、この場合はサーバ上のプロセスが端末制御を行うための仮想端末 (pty) は
割り当てられず、最終ログイン時刻などのメッセージも表示されません。
サーバ上のプロセスに強制的に端末を割り当てるには -t
オプションを指定します。
リモートコマンドを実行する |
---|
$ ssh [-p ポート番号] [-t] [ユーザ名@]ホスト名 コマンド 引数1 引数2 ... |
実行例:
client$ ssh yusuke@server.example.com ls -l (サーバ上で ls -l を実行する) Enter passphrase for key '/home/yusuke/.ssh/id_rsa': (秘密鍵のパスフレーズを入力する) drwx------ 4 yusuke users 120 Mar 27 01:19 Mail drwxr-xr-x 7 yusuke users 2184 Mar 14 14:26 bin drwxr-xr-x 5 yusuke users 344 Feb 6 19:53 lisp drwxr-xr-x 4 yusuke users 1184 Mar 8 21:27 work drwxr-xr-x 10 yusuke users 864 Mar 25 19:44 tmp drwxr-xr-x 7 yusuke users 168 Mar 6 17:00 tex client$ echo $? (ssh の終了状態を見る) 0 client$ ssh yusuke@server.example.com /bin/false (サーバ上で /bin/false を実行する) Enter passphrase for key '/home/yusuke/.ssh/id_rsa': client$ echo $? (ssh の終了状態を見る) 1
実際には、ここで指定するリモートコマンド名と引数はすべてサーバ上でひとつにまとめられ、
シェルの -c
オプションをつかって実行されるため、
[脚注: tcsh
と bash
のどちらにおいても、-c
オプションは
与えられた文字列をコマンドラインとしてじかに解釈するよう指示するものです。]
シェルのコマンドやワイルドカードによるファイル指定も使用できます。
また、複数個の引数を引用符 "〜"
で囲んで渡しても結果は変わりません。
client$ ssh yusuke@server.example.com echo "*" (サーバ上で echo * を実行する) Enter passphrase for key '/home/yusuke/.ssh/id_rsa': Mail bin lisp work tmp tex client$ ssh yusuke@server.example.com "echo *" (サーバ上で echo * を実行する) Enter passphrase for key '/home/yusuke/.ssh/id_rsa': Mail bin lisp work tmp tex
公開鍵認証をつかわない場合、OpenSSH では伝統的な UNIX のパスワードをつかった ログインもできます。ただしこの場合、パスワードの盗難に注意する必要があります (3.2.2. なりすましによるパスワードの盗難 参照)。 したがって、あるサーバにはじめて接続する時にはあらかじめそのサーバのホスト公開鍵を確認し、 実際の接続時に表示される指紋と比較できるようにしておくことが大切です。
サーバのホスト公開鍵とホスト秘密鍵は通常 sshd
の設定ファイルと同じディレクトリに
格納されています。ホスト公開鍵は一般ユーザにも読めるようになっているので、
ユーザはそのサーバに遠隔地からログインする前に、
以下のように ssh-keygen
コマンドを使ってホスト公開鍵の指紋を調べておきます:
server$ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub (RSA公開鍵の指紋を表示する) 2048 ac:62:6e:32:7e:6f:bc:6a:2f:a1:e5:f3:a5:db:7f:c0 /etc/ssh/ssh_host_rsa_key.pub server$ ssh-keygen -l -f /etc/ssh/ssh_host_dsa_key.pub (DSA公開鍵の指紋を表示する) 2048 ac:62:6e:32:7e:6f:bc:6a:2f:a1:e5:f3:a5:db:7f:c0 /etc/ssh/ssh_host_dsa_key.pub
パスワード認証のさいは、この値をどこかにメモしておくか、
サーバ管理者に問い合わせるなどして、事前に指紋を知っておくことが必要です。
その後、サーバに接続して正しい指紋が表示されれば
ユーザは安心してパスワードを入力することができます。
ssh
コマンドの使い方そのものは公開鍵認証のときと変わりません。
client$ ssh yusuke@server.example.com The authenticity of host 'server.example.com (11.22.33.44)' can't be established. RSA key fingerprint is ac:62:6e:32:7e:6f:bc:6a:2f:a1:e5:f3:a5:db:7f:c0. (ホスト公開鍵の指紋が正しいことを確認する) Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added server.example.com,11.22.33.44' (RSA) to the list of known hosts. yusuke@server.example.com's password: (パスワードを入力する) Last login: Mon Mar 13 12:05:06 2006 from xx.xx.xx.xx server$
本書では、特別な事情がある場合をのぞき公開鍵認証を使うことをおすすめします。 公開鍵認証では、たとえ何らかの理由で秘密鍵につけたパスフレーズが推測されてしまったとしても、 秘密鍵ファイルそのものを持っていなければログインされてしまうことはありません。 しかし、パスワード認証ではパスワードさえ知っていれば誰でも そのサーバにログインできてしまいます。 また、パスワード認証では、たとえ暗号化された形とはいえパスワードが ネットワーク上を流れます。いずれにせよ公開鍵認証ほど安全ではありません。
サーバ管理者からみたパスワード認証の問題点 |
---|
ユーザは、覚えやすいパスワードにしようとするあまり、 簡単に推測が可能なパスワードをつけてしまうことがよくあります。 ユーザの名前や誕生日はもちろんのこと、 辞書に載っている単語や簡単な日本語をローマ字にしたものを パスワードとして使うのは危険です。 インターネット上では、とくに 2005年ごろから辞書に載っている単語を組み合わせ ユーザ名とパスワードを多数生成し、それらを用いてサーバに繰り返しログインを試みる攻撃が多発しています。 ユーザ名としては日本語の名前を試した攻撃例も見つかっています。 そのため、パスワード認証を許可するときはパスワードの選び方に 十分注意するとともに、不審なログインの形跡がないかどうか 気をくばるようにしてください。 5.1.4. パスワード認証を安全に使うには ではパスワード認証を安全に使う方法を、 5.5.3. パスワード推測攻撃を避ける ではパスワードの推測攻撃を防ぐ方法を紹介します。 |
OpenSSH には、サーバにログインして直接シェルを動かす ssh
コマンドに加えて、
ファイルを転送するためのコマンド scp
と sftp
も用意されています。
これらはそれぞれ昔の UNIX に含まれていた rcp
と ftp
を
模倣したもので、ssh
コマンドと同じ認証方式を使い、
暗号化されたファイル転送をおこないます。
scp
は
cp
コマンドで通常のファイルをコピーする感覚で簡単に使えますが、
効率が悪く、大量のファイルを転送する用途には向きません。また、scp
コマンドは
実装の拠りどころとなる規格が策定されていないため、一部の SSH サーバでは互換性を期待できないこともあります。
いっぽう sftp
コマンドは SSH プロトコルの一部として正式に定義されていますが、
こちらは ftp
コマンドと同じく、一度 sftp
コマンドで
ログインし、内部でさらに別のコマンドを呼び出すという形をとっており、
シェルとの連携はうまくありません。
この節では、これら scp
と sftp
に加えて、
ネットワークを介したファイルの大量転送に適した rsync
コマンドと OpenSSH とを併用する方法、
さらに、Emacs 上のツールである TRAMP を使用する方法を紹介します。
scp
コマンドの使い方は簡単です。
通常の cp
コマンドでパス名を指定するかわりに、
サーバ上にあるファイルを scp
コマンドで [ユーザ名@]ホスト名:パス名
のように指定すればよいのです。ユーザ名がクライアントとサーバ上で同じ場合はユーザ名の入力を省略できます。
scp
コマンドは内部で ssh
コマンドを呼び出しているため、
ssh
と同じく、最初にホスト認証が行われ、ユーザは
公開鍵認証のパスフレーズ (あるいは、パスワード認証の場合はサーバ側のパスワード) を
入力する必要があります。
また scp
では cp
コマンドと同様、
転送元として複数のファイルを指定することもできます。
scp の使い方 |
---|
(クライアントからサーバへファイル転送) $ scp [オプション] パス名1 [パス名2 ...] [ユーザ名@]ホスト名:[パス名] (サーバからクライアントへファイル転送) $ scp [オプション] [ユーザ名@]ホスト名:パス名1 [[ユーザ名@]ホスト名:パス名2 ...] パス名 |
なお、サーバ上のパス名として絶対パスを指定しなかった場合は、そのサーバ側のホームディレクトリからの 相対パスとみなされます。代表的なオプションを 表 scp-command-options にまとめました。
オプション | 説明 |
---|---|
-q |
進捗を表示しない (quiet)。 |
-r |
ディレクトリを再帰的に転送する (recursive)。 |
-p |
転送元ファイルの更新日時やパーミッションも反映させる (preserve)。 |
-P ポート番号 |
デフォルト (TCP 22番) 以外のポート番号に接続する。 |
以下に典型的な実行例を示します。
(サーバ上の /etc/motd ファイルをカレントディレクトリに転送する) $ scp yusuke@server.example.com:/etc/motd . Enter passphrase for key '/home/yusuke/.ssh/id_rsa': (秘密鍵のパスフレーズを入力する) motd 100% 120 0.1KB/s 00:00 (book.html と book.pdf をサーバの自分のホームレディレクトリ上に転送する) $ scp book.html book.pdf yusuke@server.example.com: Enter passphrase for key '/home/yusuke/.ssh/id_rsa': (秘密鍵のパスフレーズを入力する) book.html 100% 86KB 85.7KB/s 00:01 book.pdf 100% 194KB 67.1KB/s 00:03 (mail/ ディレクトリ全体をサーバのホームレディレクトリ上にある work/ ディレクトリ内に転送する、 このとき進捗状況を表示しない) $ scp -r -q mail/ yusuke@server.example.com:work/ Enter passphrase for key '/home/yusuke/.ssh/id_rsa': (秘密鍵のパスフレーズを入力する) $
ファイルを何度かに分けて転送する場合は、 繰り返しパスフレーズを入力するのはわずらわしいと思うかもしれません。 このような場合は、認証エージェントを使うと便利です。 詳しくは 4.4. 認証エージェントを使う を参照してください。
sftp
コマンドは、
従来ファイル転送につかわれていた ftp
コマンドに似ています。
ユーザはまずサーバにログインし、その後 sftp 内部の転送コマンドを入力することで
ファイルを転送します。いくつものファイルを選びながら転送したり、
サーバ側の転送先を確認しながら転送したりしたい場合は、繰り返しログインをおこなわなければならない
scp
コマンドよりも効率的ですが、同時にいくつものコマンドを入力する
必要があるため、ファイルを 1つだけ転送するような場合に使うのはやや面倒です。
sftp
コマンドも ssh
と同じく、
最初にユーザ名とホスト名を指定してログインします。
オプションではポート番号も指定できます。
sftp の使い方 |
---|
$ sftp [-oPort=ポート番号] [ユーザ名@]ホスト名[:ディレクトリ名] |
実行例:
$ sftp yusuke@server.example.com (サーバに接続する) Connecting to server.example.com... sftp> ls -l (ファイルの一覧を表示) drwx------ 4 yusuke users 120 Mar 27 01:19 Mail drwxr-xr-x 7 yusuke users 2184 Mar 14 14:26 bin drwxr-xr-x 5 yusuke users 344 Feb 6 19:53 lisp drwxr-xr-x 4 yusuke users 1184 Mar 8 21:27 work drwxr-xr-x 10 yusuke users 864 Mar 25 19:44 tmp drwxr-xr-x 7 yusuke users 168 Mar 6 17:00 tex sftp> cd tex (リモート側のカレントディレクトリを変更する) sftp> ls -l (ファイルの一覧を表示) -rw-r--r-- 1 yusuke users 816 May 23 2005 init.tex -rw-r--r-- 1 yusuke users 431 Sep 29 2004 wide.sty -rw-r--r-- 1 yusuke users 155290 Dec 16 17:31 yusuke.bib sftp> get yusuke.bib (yusuke.bib をローカルに転送) Fetching /home/yusuke/tex/yusuke.bib to yusuke.bib /home/yusuke/tex/yusuke.bib 100% 152KB 151.7KB/s 00:01 sftp> quit (sftp を終了する) $
ftp
と同様、sftp
にも
「カレントディレクトリ」という概念があります。
コマンド実行時にディレクトリ名を指定しておくと、クライアントは
ログイン後、そのディレクトリに移動します。
ログインすると、"sftp>
" というプロンプトが表示され、
表 sftp-commands. のような内部コマンドが使用可能になります。
[脚注: ここに挙げた以外にも chown, chgrp, lmkdir, lumask, progress, version
などの
コマンドがありますが、使用頻度が低いので割愛してあります。詳しくは sftp
コマンドの
マニュアルを参照してください。]
ftp
コマンドを使ったことのある方なら、おそらく操作はたやすいでしょう。
[脚注: OpenSSH をインストールするとき configure
のオプションで
--with-libedit
を指定していると、sftp 内でも Emacs ライクなキー操作による
行編集が使えます。ただし、シェルとは違ってファイル名補完はサポートされていません。]
コマンド | 説明 |
---|---|
ヘルプを表示:help あるいは ?
| コマンドのヘルプを表示します。 |
リモートディレクトリの内容を表示:ls [オプション] [パス名]
|
リモート (サーバ側) のディレクトリの内容を一覧表示します。
パス名を指定しない場合はリモートのカレントディレクトリの内容が表示されます。
通常の ls コマンドと同じく、
-a (ドットで始まるファイルも表示),
-l (詳細な情報を表示),
-t (更新日時でソート)
などのオプションが使用できます。
|
ローカルディレクトリの内容を表示:lls [オプション] [パス名]
|
ローカル (クライアント側) のディレクトリの内容を一覧表示します。
パス名を指定しない場合はローカルのカレントディレクトリの内容が表示されます。
ここで指定されたオプションは、ローカルの ls コマンドに渡されます。
|
リモート→ローカル転送:get [-P] リモートパス名 [ローカルパス名]
|
ファイルをローカル (クライアント側) に転送します。
ローカルパス名が指定されない場合は、(クライアントの)
カレントディレクトリ上に転送されます。
-P オプションを指定すると、
ファイルのパーミッションや更新日時をリモート側のファイルに揃えます。
なお、ディレクトリをまるごと転送することはできません。
|
ローカル→リモート転送:put [-P] ローカルパス名 [リモートパス名]
|
ファイルをリモート (サーバ側) に転送します。
リモートパス名を指定しない場合は、(サーバの) カレントディレクトリ上に転送されます。
-P オプションが指定すると、
ファイルのパーミッションや更新日時をローカル側のファイルに揃えます。
なお、ディレクトリをまるごと転送することはできません。
|
リモートのカレントディレクトリ変更:cd リモートパス名
| リモート (サーバ側) のカレントディレクトリを変更します。 |
ローカルのカレントディレクトリ変更:lcd リモートパス名
| ローカル (クライアント側) のカレントディレクトリを変更します。 |
リモートのカレントディレクトリのパス名を見る:pwd
| リモート (サーバ側) のカレントディレクトリのパス名を表示します。 |
ローカルのカレントディレクトリのパス名を見る:lpwd
| ローカル (クライアント側) のカレントディレクトリのパス名を表示します。 |
sftp を終了する:exit または quit
|
ログアウトし、sftp を終了します。
|
コマンド | 説明 |
---|---|
リモートのファイル名を変更:rename 旧パス名 新パス名
|
リモート (サーバ側) のファイルあるいはディレクトリ名を変更します。
UNIX の mv コマンドとは異なり、ファイルやディレクトリの移動には使えません。
また、すでに存在するファイル名を上書きすることはできません。
|
リモートのファイルを消去:rm パス名
|
リモート (サーバ側) のファイルを削除します。
UNIX の rm コマンドとは異なり、ディレクトリをまるごと削除することはできません。
|
リモートのパーミッションを変更:chmod パーミッション パス名
|
リモート (サーバ側) ファイルのパーミッションを変更します。
UNIX の chmod コマンドとは異なり、
ディレクトリ中のファイルすべてを変更することはできません。
|
リモートのディレクトリを新規作成:mkdir パス名
| リモート (サーバ側) で新しいディレクトリを作成します。 |
リモートのディレクトリを削除:rmdir パス名
| リモート (サーバ側) のディレクトリを削除します。 そのディレクトリ中にまだファイルが存在している場合はエラーになります。 |
リモートのシンボリックリンクを作成:symlink リンク先パス名 リンク元パス名
| リモート (サーバ側) にシンボリックリンクを作成します。 そのリンク元のパス名がすでに存在している場合はエラーになります。 |
ローカルでシェルを実行:! コマンド あるいは ! のみ
| ローカルのクライアント上でシェルを呼び出し、コマンドを実行します。 コマンドが指定されていない場合は、子プロセスとしてシェルを起動します。 |
sftp
の大きな欠点は、
ディレクトリをまるごと再帰的に転送できないことです。
このため、大量のファイルを一度に転送する場合は
rsync
を使うことをおすすめします (4.3.3. rsync をつかったファイル転送 参照)。
より対話的な機能を望む場合は、
UNIX で Emacs エディタを使っている方なら、
TRAMP というパッケージを使う方法があります (4.3.4. TRAMP をつかったファイル転送 参照)。
rsync
は OpenSSH の一部ではありませんが、
ネットワーク経由で大量のファイルを転送したり、
バックアップをおこなったりするためのツールとして普及しています。
ほとんどのオペレーティングシステムでは標準でパッケージが提供されており、
OpenSSH との連携もあらかじめ考慮されいるため、インストールしておくことをおすすめします。
ソースコードからインストールする場合は rsync の公式サイト
[脚注: http://www.samba.org/rsync/]
からダウンロードしてください。
なお、rsync はクライアントとサーバの両方にインストールする必要があります。
古いバージョンの rsync で OpenSSH を使った転送をするためには、
あらかじめクライアント上で環境変数 RSYNC_RSH
に
ssh
を指定しておく必要があります:
[脚注: rsync-2.6.6 以降のバージョンはデフォルトで ssh を使うようになっているので、
環境変数を指定する必要はありません]
(bash を使っている場合) $ export RSYNC_RSH=ssh (tcsh を使っている場合) % setenv RSYNC_RSH ssh
rsync
の使い方は scp
に似ており、いたって簡単です。
ただしディレクトリを再帰的に転送する場合、パス名の指定方法に違いがあるので注意してください。
[脚注: rsync では、転送元のディレクトリ名の最後にスラッシュ (/
) がつくか
つかないかで意味が大きく違います。ディレクトリ名の最後にスラッシュがつかない場合、
それはそのディレクトリをまるごと (そのディレクトリを含めて) 転送することを意味しますが、
ディレクトリ名の最後にスラッシュがつく場合、それはそのディレクトリ中の個々の項目を転送することを意味します。
たとえば、X というディレクトリの中に Y と Z という 2つのファイルがあるとして、
rsync -a X dest/
はディレクトリ X をまるごと dest/
の中に転送し、
dest/X
というディレクトリをつくります (dest/
がない場合は自動的に作成されます)。
いっぽう、rsync -a X/ dest/
は X の中にある全てのファイル (Y と Z) を
dest/
の中に転送しますが、ディレクトリ X そのものは転送しません。]
rsync の使い方 |
---|
(クライアントからサーバへファイル転送) $ rsync -a [オプション] パス名 [パス名 ...] [ユーザ名@]ホスト名:[パス名] (サーバからクライアントへファイル転送) $ rsync -a [オプション] [ユーザ名@]ホスト名:パス名 [[ユーザ名@]ホスト名:パス名 ...] |
実行例:
(サーバ上の/opt/yusuke
というディレクトリのコピーを、ローカルの backup/ ディレクトリの中に作成する) $ rsync -a yusuke@server.example.com:/opt/yusuke backup (サーバ上の yusuke ホームディレクトリ中の work というディレクトリを、ローカルの work/ ディレクトリと同期させる) $ rsync -a yusuke@server.example.com:work/ work/
ここで使用している -a
オプションはディレクトリの再帰的な転送を可能にするもので、
これは同時にパーミッションや更新日時、シンボリックリンクなども正しく複製します。
rsync
は scp
に比べはるかに多くの機能をサポートしており、
単なるディレクトリの転送だけでなく、新しく更新したファイルのみを転送したり、
特定のパターンにマッチするファイルを除いたりすることもできます。
よく使われるオプションを表 rsync-options. に示しました。詳細については rsync のマニュアルを参照してください。
オプション | 説明 |
---|---|
-a |
ディレクトリを再帰的に転送し、パーミッションや更新日時、 シンボリックリンクなどの情報を可能なかぎり忠実に複製する (archival)。 |
-u |
更新モード (update)。より新しいファイルが転送先にある場合は、そのファイルを転送しない。 |
-b |
バックアップ (backup)。転送先のファイルを上書きする場合、古いファイルのバックアップを作成する。 |
-v |
冗長表示モード (verbose)。転送するファイル名を逐一表示する。 |
-z |
圧縮を使用する (gzip)。 OpenSSH の設定ですでに通信の圧縮を指定している場合は、 このオプションは必要ありません。 |
-e "コマンド" |
ssh のかわりに実行するコマンドを指定する。
ssh で接続する際にオプションが必要な場合は、
-e "ssh -p22" のように指定できます。
|
--delete |
転送元にはないファイルが転送先のディレクトリにあった場合、そのファイルを削除する。 |
--exclude パターン |
指定されたパターンに合致するファイル名を無視する。 |
rsync
はクライアントとサーバの両方で実行されます。
まずクライアント側で実行された rsync
コマンドが、
内部で ssh
コマンドを呼び出し、サーバ側の rsync
を
リモートコマンドとして実行します (図 rsync-client-server)。
その後、この 2つのプロセスは
それぞれローカルとリモート上にある転送元と転送先のファイルを比較し、
ネットワーク転送量を最小限に抑えるような差分を送信します。
そのため、rsync
はネットワーク経由で安全にバックアップをするのに最適です。
6.1.3. rsync を使ってネットワーク経由でバックアップする では rsync
をつかった定期的なバックアップの方法を紹介しています。
TRAMP は Emacs エディタ上で動く ssh
コマンドのフロントエンドで、
Emacs 上の dired
コマンドに似たインターフェイスを用いて
サーバ上のファイルを直接編集することができます。
TRAMP は、GNU TRAMP のページ
[脚注: http://www.gnu.org/software/tramp/]
から入手できます。Emacs がデフォルトで参照するディレクトリに
正しくインストールすると、Emacs の起動と同時に TRAMP が
使用可能になっているはずです。TRAMP では
リモートホストと通信するのにいくつかの異なる方法を選べますが、
最新版ではデフォルトで "ssh
" が選択されています。
したがって、公開鍵認証 (あるいはパスワード認証) をおこなう準備が
できてさえいれば、Emacs の C-x C-f
(find-file) コマンドで
のようなパス名を開くことでリモートホスト上のファイルを直接編集できます。Find file: /ユーザ名@ホスト名:パス名
TRAMP の実行画面 |
---|
|
TRAMP は一度設定してしまえば大変便利なのですが、
ssh
コマンドを呼び出してリモートのシェルに対話的に
コマンドを送信しているため、安定性の面でやや問題があります。
また、TRAMP は Emacs が起動しているあいだ ssh
を
つなぎっぱなしにするため、セキュリティ的にも疑問が残ります。
OpenSSH を使い慣れたユーザが頻繁にファイル転送を行うときのみ使用するのがよいでしょう。
注意: TRAMP が動かない場合は |
---|
リモートホストのシェルプロンプトの設定によっては、
TRAMP はうまく動かないことがあります。筆者の環境では、以下のような設定を
.emacs ファイルに書く必要がありました。
(custom-set-default tramp-methods '(("ssh" (tramp-login-program "ssh") (tramp-copy-program nil) (tramp-remote-sh "/bin/sh") (tramp-login-args (("%h") ("-e" "none") ("-t") ("/bin/sh"))) (tramp-copy-args nil) (tramp-copy-keep-date-arg nil) (tramp-password-end-of-line nil)))) |
これまで説明してきた公開鍵認証を使ったログインでは、 ログインのたびに秘密鍵を復元するためのパスフレーズを入力する必要がありました。 しかし、いろいろなホストに繰り返しログインしなければならないような状況では、 パスフレーズの入力がユーザの負担となってしまいます。公開鍵認証を使うことの大きなメリットのひとつに、 ユーザが認証エージェント (authentication agent) を使って、 パスフレーズ入力を省略できることがあげられます。
認証エージェント (3.3.3. 認証エージェントを使った認証 参照)
とはユーザにかわって認証を行ってくれるプログラムのことで、
その本体は、ssh
クライアントとは別個に起動する
ssh-agent
と呼ばれるプログラムです。
これは OpenSSH のパッケージに含まれており、
その他のプログラムとともに自動的にインストールされます。
まずは使ってみることにしましょう。
ユーザは ssh
コマンドの実行に先立って
あらかじめ ssh-agent
を起動しておき、
パスフレーズを入力して復元した秘密鍵を登録します。
ssh-agent
を起動するには 2通りのやり方がありますが、
ここでは ssh-agent
の子プロセスとしてシェルを起動する方法を紹介します。
(tcsh
を使っている方は、以下の例で ssh-agent bash
と実行するかわりに
ssh-agent tcsh
と実行してください。)
注意 |
---|
本書では ssh-agent を引数なしで起動することはおすすめしません。
引数なしで ssh-agent を起動した場合、これはまったく異なる動きをします。
引数なしで ssh-agent を起動してしまった場合は、
ps コマンドで ssh-agent のプロセス ID を確認し kill してください。
詳しくは 4.4.4. 認証エージェントを使う際の注意 を参照してください。
|
認証エージェントを起動する |
---|
(bash を使っている場合) $ ssh-agent bash (tcsh を使っている場合) $ ssh-agent tcsh |
実行例:
client$ ssh-agent bash (認証エージェントを起動する) (以後、子プロセスのシェル)
ssh-agent
は引数として渡されたコマンド名を子プロセスとして実行します。
ここではまず ssh-agent
コマンドの子プロセスとして、
さらにシェルを起動させています。
client$ ps (プロセス一覧を見る) PID TTY STAT TIME COMMAND 14928 pts/7 S 0:00 -bash 15016 pts/7 S 0:00 bash (子プロセスのシェル) 15017 ? S 0:00 ssh-agent bash 15026 pts/7 R 0:00 ps x
では次に ssh-add
コマンドを使って秘密鍵を登録します。
認証エージェントに秘密鍵を追加する |
---|
$ ssh-add [秘密鍵ファイル] |
実行例:
client$ ssh-add (認証エージェントに秘密鍵を追加する) Enter passphrase for /home/yusuke/.ssh/id_rsa: (秘密鍵のパスフレーズを入力する) Identity added: /home/yusuke/.ssh/id_rsa (/home/yusuke/.ssh/id_rsa)
ssh-add
コマンドは親プロセスである ssh-agent
と通信し、
パスフレーズの入力によって復元された秘密鍵を ssh-agent
プロセスのメモリ上に登録します。
鍵が登録されているかどうかは、ssh-add -l
を実行することにより確認できます。
認証エージェントが保持している鍵を確認する |
---|
$ ssh-add -l |
実行例:
client$ ssh-add -l (認証エージェントの持っている鍵の一覧を表示する) 2048 23:56:6e:90:f3:98:fc:7b:2a:92:fb:46:bf:20:98:71 /home/yusuke/.ssh/id_rsa (RSA) (鍵の指紋が表示される)
こうすることにより、これ以後
パスフレーズを入力しなくても ssh
コマンドで
サーバにログインできるようになります。
client$ ssh server.example.com (サーバにログインする) Last login: Mon Mar 15 08:47:11 2006 from xx.xx.xx.xx (パスフレーズの入力は要求されない) server$
ひとたび秘密鍵を登録してしまえば、パスフレーズの入力なしで、 同一のサーバに繰り返しログインできるはずです:
... server$ logout (サーバからログアウトする) Connection server.example.com closed. client$ sftp server.example.com (ふたたび SFTP でログインする) Connecting server.example.com... (パスフレーズの入力は要求されない) sftp>
最後に、サーバへのログインが必要なくなったら、exit
を入力して
このシェルを終了します。すると同時に ssh-agent も終了し、
メモリ上の秘密鍵は失われます:
client$ exit (子プロセスを終了する) (元のプロセスのシェルに戻る) client$ ps (プロセス一覧を見る) PID TTY STAT TIME COMMAND 14928 pts/7 S 0:00 -bash 15821 pts/7 R 0:00 ps x client$ ssh-add -l (認証エージェントの持っている鍵の一覧を表示する) Could not open a connection to your authentication agent. (認証エージェントと通信できない)
まとめると、認証エージェントを使う手順は以下のようになります:
ssh
コマンドの実行に先だって、ssh-agent
を起動する。
ssh-add
コマンドを実行してパスフレーズを入力し、ssh-agent
プロセスに秘密鍵を登録する。
ssh
コマンドを実行してサーバにログインする。(パスフレーズは要求されない)
ssh
コマンドの実行が終わったあと、ssh-agent
プロセスを終了する。ssh-agent
が必要とされるのは認証の時だけなので、
実際には最後の認証を終えてしまったら、あとは ssh
を終了するまえに
ssh-agent
を終了してもかまいません。]
認証エージェントを使う場合、3つのプログラム
(ssh
, ssh-agent
および ssh-add
) が
協調して動作するため、そのしくみはやや複雑です。
UNIX では伝統的に「あるコマンドは、ひとつの仕事だけを実行して終了する」という
考え方が一般的です。ssh
コマンドもこの考え方に沿って設計されています。
そのため ssh
コマンドが秘密鍵を扱う場合は、毎回ユーザが
パスフレーズを入力してディスク上の暗号化された秘密鍵を復元してやらねばならず、
ssh
が終了すると復元された鍵は失われてしまいます。
ssh-agent
はこの問題を解決するため、
ssh
コマンドとは別のプロセスとして起動し、
ssh
と通信するという方法を採用しています。
これは個人用のデーモンプロセスのようにふるまい、
通常すべての ssh
コマンドが実行される前に起動され、
すべてのユーザ認証が終わるまで走りつづけることになります (図 timeline-ssh-agent)。
ssh
と ssh-agent
サーバが「秘密鍵の所有を証明せよ」と要求してきたとき、
ssh
コマンドは、最初に認証エージェントと通信しようと試みます。
認証エージェントがその秘密鍵を保持していれば、
ssh
コマンドはユーザにパスフレーズの入力を求めることなく、
認証エージェントにサーバからの要求 (チャレンジ) を中継します。
認証エージェントは秘密鍵をつかって、それを所有していることの証明
(レスポンス) を生成し、ssh
コマンドを経由してサーバに送信します。
ssh-agent
は秘密鍵を一度使用したあとも破壊せずメモリ中に
保持しつづけるので、サーバからのチャレンジに何度でも応えることができます。
こうしてユーザはパスフレーズを一度入力するだけで
サーバに繰り返しログインできるというわけです。
OpenSSH では、ssh-agent
と ssh
との通信に
UNIX ドメインソケットを使っています。UNIX ドメインソケットは同一ホスト上で動いている
プロセス同士が通信するための機構で、ファイルシステム上では
あたかも読み書きできるファイルのようにふるまいます。
OpenSSH では、このソケットのパス名は SSH_AUTH_SOCK
という
環境変数に格納されると決められています。
したがって、現在認証エージェントが使用可能かどうかは
環境変数 SSH_AUTH_SOCK
を調べることでも判定できます。
client$ echo $SSH_AUTH_SOCK (SSH_AUTH_SOCK の値を確認する) (中身は空) client$ ssh-agent bash (認証エージェントを起動する)(以下、子プロセスのシェル) client$ echo $SSH_AUTH_SOCK (SSH_AUTH_SOCK の値を確認する) /tmp/ssh-EWMhQ17474/agent.17474 (通信用ソケットのパス名が入っている) client$ ls -l $SSH_AUTH_SOCK (通信用ソケットの実体を確認する) srw------- 1 yusuke users 0 Mar 18 17:07 /tmp/ssh-EWMhQ17474/agent.17474 client$ exit (認証エージェントを終了する)(親プロセスのシェルに戻る) client$ echo $SSH_AUTH_SOCK (SSH_AUTH_SOCK の値を確認する) (ふたたび中身は空) client$ ls -l /tmp/ssh-EWMhQ17474/agent.17474 ls: /tmp/ssh-EWMhQ17474/agent.17474: No such file or directory (通信用ソケットは削除されている)
ssh
を起動したとき、ssh
はまずこの
SSH_AUTH_SOCK
という環境変数が設定されているかどうかを調べ、
設定されている場合はここで指定されている通信用ソケットを使って、
ssh-agent
との通信をこころみます。ssh-agent
が存在している場合、
ssh
はサーバからの認証要求をすべて ssh-agent
に中継します。
また認証エージェントに秘密鍵を登録する ssh-add
も
同じ UNIXドメインソケットを使って ssh-agent
と通信し、
ssh-agent
プロセスが保持している秘密鍵の追加や削除を行います (図 interaction-ssh-agent)。
認証エージェントをつねに子プロセスから使わなければならないのは、
この環境変数 SSH_AUTH_SOCK
の内容を ssh
コマンドや
ssh-add
コマンドに伝える必要があるためです。
UNIX では、あるプロセスの環境変数を他のプロセスから操作できません。
ただし、新しいプロセスを親プロセスから起動するときだけは環境変数を「継承する」ことができます。
そのため ssh-agent
は認証エージェントを使うプロセスを子プロセスとして起動し、
SSH_AUTH_SOCK
環境変数を継承するようになっています (図 inherit-env-with-ssh-agent)。
SSH_AUTH_SOCK
を子プロセスに継承する
認証エージェントには、 ユーザがあるサーバを経由してさらに別のサーバにログインするときに、 現在使っている認証エージェントを「転送」できるという機能があります。 あるサーバからさらに別のサーバへログインしなければならない場合を 考えてみましょう (図 multiple-login)。
サーバ 2 にログインするには、
サーバ 1 上の ssh
コマンドで公開鍵認証を行わなくてはなりません。
しかしこのためにはサーバ 1 上に秘密鍵の入った id_rsa
ファイルを
置く必要がありますし、ネットワーク経由でこの秘密鍵を復元するためのパスフレーズを入力する必要があります。
このような場合、認証エージェントの転送機能を使うと、
サーバ 2 にログインするときも、クライアントの認証エージェントが保持する秘密鍵を
使うことができます。
認証エージェントの転送を許可してログインする |
---|
$ ssh -A [ユーザ名@]ホスト名 |
実行例:
client$ ssh-agent bash (認証エージェントを起動する) ... client$ ssh -A yusuke@server1.example.com (エージェントの転送を許可してサーバにログイン) Last login: Mon Mar 15 08:47:11 2006 from xx.xx.xx.xx (パスフレーズの入力は要求されない) server1$ ssh yusuke@server2.example.com (さらにべつのサーバにログインする) Last login: Mon Mar 04 17:21:09 2006 from xx.xx.xx.xx (パスフレーズの入力は要求されない) server2$
ssh
コマンドに -A
オプションをつけると、
クライアントはローカルで動いている認証エージェントの情報をサーバ 1 に通知し、
サーバ 1 上の sshd
デーモンが認証エージェントとしても機能するようになります。
この状態でさらにサーバ 2 へのログインを試みると、
サーバ 2 による認証の要求はサーバ 1 の
ssh
、 sshd
を経由してクライアントの ssh
に中継され、
さらにそこから ssh-agent
へと中継されることになります
(図 relaying-authentication-agent)。
サーバ 1 にログインした後で環境変数 SSH_AUTH_SOCK
の値を確認してみると、
クライアントの SSH_AUTH_SOCK
とは別の値が入っていることに気づくでしょう。
この通信用ソケットはサーバ 1 上で動いている
sshd
が用意したもので、このデーモンが
クライアントの認証エージェントの機能を「転送」していることを示しています。
client$ ssh-agent bash (認証エージェントを起動する) client$ echo $SSH_AUTH_SOCK (SSH_AUTH_SOCK の値を確認する) /tmp/ssh-EWMhQ17474/agent.17474 client$ ssh -A yusuke@server1.example.com Last login: Mon Mar 15 08:47:11 2006 from xx.xx.xx.xx server1$ echo $SSH_AUTH_SOCK (SSH_AUTH_SOCK の値を確認する) /tmp/ssh-mgdxeOv740/agent.740 (別のパス名が入っている)
認証エージェントは便利ですが、以下のような点に注意してください。
ssh-agent
プロセスと ssh
プロセスの通信は
暗号化されていないため、もしそのユーザ以外のプロセスが
この通信用ソケットにアクセスできると、そのプロセスは
簡単にそのユーザになりすますことができてしまいます。
[脚注: ただし ssh-agent
は秘密鍵そのものを相手に渡すわけではないので、
プロセスのメモリ空間に直にアクセスしないかぎり、復元された状態の秘密鍵が
盗まれることはありません。]
同様に、リモートのサーバ上に転送された認証エージェント
(実体は sshd
プロセス) と ssh
プロセスの通信も暗号化されていません。
通常、認証エージェントは通信用ソケットのパーミッションを
そのユーザのみがアクセス可能なように設定しますが、root 権限で動いているプロセスは
このパーミッションを無視できます。
したがって、認証エージェントを使うマシン、および転送をになうサーバはその管理者を含め、
十分に信頼できる必要があります。
デフォルトでは、ssh-agent
は
一度復元した秘密鍵を終了するまで保持しつづけます。
これは実のところ危険です。あるクライアントを長時間使いつづけている場合、
ssh-agent
を立ちあげたまま放置しておくことは、
サーバにログインしたままで長時間席を離れるのと同じ危険がともないます。
このため ssh-add
には認証エージェントが保持する
秘密鍵の生存時間を指定する機能があります。
生存時間を指定して秘密鍵を追加する |
---|
$ ssh-add -t 秒数 [秘密鍵ファイル] |
実行例:
$ ssh-add -t 3600 (1時間だけ有効な秘密鍵を認証エージェントに追加する)
この方法で追加された秘密鍵は、指定された時間が経過すると自動的に
認証エージェントによってメモリ中から消去されます。同じ秘密鍵をふたたび使用したい場合には
再度 ssh-add
コマンドでパスフレーズを入力しなければなりません。
なお、-t
オプションをつけない場合、秘密鍵の生存時間は
ssh-agent
起動時に指定された値になります。
デフォルトではこの値は無限大 (ssh-agent
が終了するまで保持しつづける) になっています。
秘密鍵の生存時間を指定した安全な認証エージェントの使い方については
5.1.3. 認証エージェントの使用を支援する を参照してください。
また、以下のように ssh-add -D
コマンドを実行することで
認証エージェントに登録されている鍵をいったんすべて削除することができます。
認証エージェントの鍵をすべて削除する |
---|
$ ssh-add -D |
実行例:
client$ ssh-add -l (認証エージェントの持っている鍵の一覧を表示する) 2048 23:56:6e:90:f3:98:fc:7b:2a:92:fb:46:bf:20:98:71 /home/yusuke/.ssh/id_rsa (RSA) client$ ssh-add -D (認証エージェントの鍵をすべて削除する) All identities removed. client$ ssh-add -l The agent has no identities. (鍵は削除された)
ssh-agent
にはもうひとつ別の起動方法があります。
ssh-agent
を引数なしで実行すると、ssh-agent
は子プロセスのシェルを起動せず、
ssh-agent
を実行したシェルと並列にバックグラウンドで走ります。
このとき ssh-agent
は標準出力に
環境変数 SSH_AUTH_SOCK
を設定するシェルのコマンド列を出力します。
シェルはこのコマンド列を eval
により実行することで通信用ソケットの位置を
獲得します。この方法は本書ではおすすめしません。
なぜなら子プロセスを使った方法よりもわかりにくいうえに、
認証エージェントを終了し忘れる可能性があるからです。
認証エージェントに子プロセスのシェルを起動させるようにすれば、
このシェルを終了したときに確実に認証エージェントも終了します。
しかし、それでも ssh-agent
を手動で起動すると、
うっかり引数なしで起動してしまうミスを犯してしまうかもしれません。
そのため本書では、ログイン時に自動的に認証エージェントが起動されるように
あらかじめ管理者がクライアントを設定しておくことをおすすめします。
この方法については ユーザがログインした瞬間から ssh-agent を走らせる を参照してください。
OpenSSH を使うとリモートホスト上で通常の端末ベースのアプリケーションに加えて、 X11 による画面描画をおこなうアプリケーション (X クライアント) を 実行することができます。
UNIX で伝統的に使われている画面描画システムである
X Window System (X11) は、画面の描画をクライアント・サーバモデルでおこなっています。
通常ローカルホスト上で xterm
や firefox
などの
X11 アプリケーションを実行すると、これらのプログラムは
別に走っている X サーバプロセスと通信して画面制御を行います。
ここで実際に画面描画を行っているのは X サーバプロセスで、
X11 アプリケーションはこのプロセスに描画を要求するクライアントです。
このとき、Xサーバと通信するためのネットワークソケットの位置は環境変数 DISPLAY
に
格納されると取り決められており、各 X11 アプリケーションは環境変数 DISPLAY
の
値をもとに Xサーバと通信します (図 xserver-local)。
従来の X Window System では、ユーザがリモートホストにログインした際、 外部のホストからローカルな Xサーバの通信用ソケットにアクセスすることを許していました (図 xerver-danger)。しかしこの通信は暗号化されていなかったため、 X クライアントが画面に表示した内容や、ユーザからのキーボード入力が ネットワーク上の第三者に盗聴されてしまうという危険性がありました。 また、この状態では第三者が通信内容に手を加え、 ユーザのマシンにアクセスすることも可能です。
OpenSSH では、通常の文字ベース (端末ベース) の通信に加えて、
リモートホストとローカルな X サーバの間の通信も暗号化することができます。
OpenSSH はサーバとクライアント間で複数の情報を同時に送受信できるように設計されており、
文字ベースの情報だけでなく X11 の通信や、その他の TCP 通信なども
暗号化することが可能です。
[脚注: TCP 通信の暗号化 (ポート転送) については 6.2. ポート転送 を参照してください。]
具体的にはユーザがログインしたサーバ上の sshd
デーモンが
擬似 Xサーバとしてふるまい、リモートホスト上の Xクライアントの要求を
ローカルな Xサーバに中継します (図 xserver-forwarding)。
これを X11 転送 (X11 forwarding) と呼びます。
この間もリモートホスト上で実行されている通常のシェルとの
端末ベースの通信も同時並列的に行われます。
OpenSSH で X11 転送を使うには、まずサーバ側の
sshd
の設定を変更する必要があります。
OpenSSH のデフォルトの設定では X11 転送は禁止されているため、
ユーザが X11 転送を使うためには、まずシステム管理者が
サーバ上の sshd_config
設定ファイルを以下のように
修正します。
[脚注: sshd
サーバデーモンの設定を変える詳しい方法については
5.2. sshd を安全に設定する を参照してください。]
X11 転送を許可する |
---|
sshd_config 設定ファイル:X11Forwarding yes |
この後、クライアントから X11転送を使うには ssh
コマンドで
ログインするときに -X
オプションを指定します。
現在のところこの指定はログイン時に行う必要があり、
ログインしたあとで設定を変えることはできません。
X11 転送を許可してログインする |
---|
$ ssh -X [ユーザ名@]ホスト名 |
実行例:
client$ ssh -X yusuke@server.example.com (X11転送を許可してログインする) Enter passphrase for key '/home/yusuke/.ssh/id_rsa': Last login: Mon Mar 24 18:00:09 2006 from xx.xx.xx.xx server$ xterm & (サーバ上で xterm を起動する) [1] 4454 server$
X11 転送をしている間はクライアント上の ssh
コマンドが
ローカルな X サーバにとっての実質的なクライアントとなります。
したがって、X11 転送を行うにはローカルマシン上で ssh
コマンドを
実行するときに環境変数 DISPLAY
の値が正しく設定されている必要があります。
通常、ローカルな xterm
ウィンドウの中などから
ssh
を実行した場合、
環境変数 DISPLAY
はすでに正しく設定されているので、
特別な操作は必要ありません。
なお、この環境変数 DISPLAY
はログインしたサーバ上では
異なる値に設定されています。以下の例でサーバ上の
DISPLAY
に格納されている localhost:10.0
という値は、
サーバ上の sshd
プロセスが設置した擬似 Xサーバの通信用ソケットです。
この値はサーバにログインした時に自動的に設定されます。
また、リモートで走っている X11 アプリケーションは通常どおり
環境変数 DISPLAY
の値をたよりに Xサーバと通信するので、
これによってリモートホスト上のアプリケーションは何も意識することなく、
暗号化された通信を使用できるわけです。
client$ echo $DISPLAY (環境変数 DISPLAY の値を確認する) :0.0 client$ ssh -X yusuke@server.example.com Enter passphrase for key '/home/yusuke/.ssh/id_rsa': Last login: Mon Mar 24 18:02:11 2006 from xx.xx.xx.xx server$ echo $DISPLAY (環境変数 DISPLAY の値を確認する) localhost:10.0
なお、X11転送を使ってバックグラウンドで X11 アプリケーションを
走らせている場合は、たとえリモートホストのシェルからログアウトした後も、
すべての X11 アプリケーションが終了するまで ssh
は
走りつづけることに注意してください。これは ssh
が
依然として X11 アプリケーションによる通信を転送する必要があるためです。
このような場合は、エスケープシーケンス (4.1.3. 公開鍵認証でログインする 参照) を使うことで、
ログアウト後に X11転送を続けている ssh
プロセスを
バックグラウンド化することができます。
実行例:
client$ ssh -X yusuke@server.example.com Enter passphrase for key '/home/yusuke/.ssh/id_rsa': Last login: Mon Mar 24 18:00:09 2006 from xx.xx.xx.xx server$ xterm & [1] 4454 server$ exit logout (サーバ上で実行した xterm が終了するまで待っている) (ここで ~& を入力する) ~& [backgrounded] (ssh がバックグラウンド化された) client$
OpenSSH のデフォルトの設定で X11 転送が禁止されているのには
理由があります。認証エージェントの転送 (4.4.4. 認証エージェントを使う際の注意 参照) と同じように、
X11 の転送はログインしたサーバが信頼できない場合には悪用される危険があるからです。
たとえば、通常は環境変数 DISPLAY
で指定されている
通信用ソケットにはログインしたユーザ以外がアクセスすることはできませんが、
リモートマシン上で root 権限をもっているプロセスならアクセスできます。
X11 の描画要求の中には同じ画面上に表示されている別のウィンドウにアクセスする機能もあるので、
リモートマシン上で X11 転送が悪用されると、ユーザの画面上にある別のウィンドウの
内容が盗み見られてあり、ウィンドウの勝手な文字が入力されたりする危険があります。
このため OpenSSH ではサーバからクライアントに転送される X11 描画要求のうち、
危険なものをあらかじめ禁止しています。具体的には、サーバ上のプロセスが所有していない
ウィンドウの中身を見ることや、xrdb
などのコマンドで
Xサーバのリソースデータベースの内容を改変することなどです。
これらの X11 要求を禁止することで悪用の被害は最小限に抑えることができますが、
ウィンドウ内容をダンプする xwd
や xmag
などの
プログラムは正しく動きません。
client$ ssh -X yusuke@server.example.com Enter passphrase for key '/home/yusuke/.ssh/id_rsa': Last login: Mon Mar 24 18:02:11 2006 from xx.xx.xx.xx server$ xwd X Error of failed request: BadWindow (invalid Window parameter) Major opcode of failed request: 3 (X_GetWindowAttributes) Resource id in failed request: 0xc0000d Serial number of failed request: 46 Current serial number in output stream: 47 server$
このような現象を回避するために OpenSSH では「信頼された X11 転送」
(Trusted X11 Forwarding) の機能も用意されています。
信頼された X11 転送では、危険な描画要求をふくむ X11 のすべての通信が
転送されます。ssh
コマンドに -Y
オプションを
与えることにで信頼された X11 転送をつかったログインが可能ですが、
このオプションを使うのは、サーバが管理者を含めて十分に信頼できる時のみにしてください。
信頼された X11 転送を許可してログインする |
---|
$ ssh -Y [ユーザ名@]ホスト名 |
この節では Windows や Mac OS X 上で、OpenSSH 以外の SSH クライアントを
使う方法を説明します。なお Windows 上の擬似 UNIX 環境である Cygwin には OpenSSH の
ssh
コマンドが含まれているため、ユーザはこれまで紹介した通りの方法で
ssh
コマンドや認証エージェントを使えます。
PuTTY は Windows 上で広く使われている SSH クライアントです。 軽量かつ小型であり、フロッピーディスク一枚に入るサイズであることから、 なにかの都合で Windows マシンを使わなければならい事態となっても容易に使うことができます。 また、日本語の表示・入力を可能にするパッチも用意されています。
PuTTY は公式配布サイト
[脚注: http://www.chiark.greenend.org.uk/~sgtatham/putty/]、
あるいは日本語パッチの配布サイト
[脚注: http://hp.vector.co.jp/authors/VA024651/#PuTTYkj_top]
からダウンロードできます。
公式配布サイトからは補助ツールもダウンロードできるので、
putty.exe
(クライアント) のほかに、
puttygen.exe
(秘密鍵と公開鍵の生成・変換ツール) と
pageant.exe
(認証エージェント) もダウンロードしておくとよいでしょう。
また、この puttygen.exe
は後述する WinSCP を使用するときにも必要になります。
OpenSSH クライアントと同じく、PuTTY でも公開鍵認証が使用できます。
補助ツールである puttygen.exe
を使うと、
秘密鍵と公開鍵のペアを生成できます。PuTTY で秘密鍵を生成すると、
これは .ppk
という拡張子で保存されます。
この .ppk
という秘密鍵の形式は
OpenSSH の id_rsa
で使われている形式とは互換性がないため、
OpenSSH の ssh-keygen
で作成した秘密鍵を
PuTTY で使用するには、あらかじめ puttygen.exe
を使って
.ppk
形式に変換しておく必要があります。
まず puttygen.exe
を起動し、"Conversions" メニューから
"Import Key..." を選択します。秘密鍵ファイルを選んでパスフレーズを入力すると
図 puttygen のように秘密鍵に関する情報が表示されます。
この後 "Save Private Key" ボタンを押して .ppk
形式を
保存してください。
PuTTY を実行すると、最初に図 putty-session. のような ウインドウが表示されます。ここに接続先のホスト名とポート番号を入力して 「Open」ボタンを押すと、黒い端末ウィンドウが現われ、ユーザ名と パスワード (あるいはパスフレーズ) の入力が促されます。
公開鍵認証をおこなう場合は、左側の Category: から
「Connection - SSH - Auth」という項目を選び、Private key file for authentication: に対して、
.ppk
形式の秘密鍵ファイルへのパス名を指定します (図 putty-pubkey)。
この後「Open」ボタンを押し、端末ウィンドウ中でパスフレーズを入力すると
公開鍵認証がおこなわれます。
なお、OpenSSH と同じように、あるホストにはじめて 接続した場合はホスト公開鍵が不明であるとの警告が表示されます (図 putty-warning)。ここで「Yes」を押すとそのホスト公開鍵が Windows のレジストリに追加され、「Cancel」を押すと接続を拒否します。 「No」を押した場合はホスト公開鍵をレジストリに追加せずに接続を続行します。 パスワード認証を使う場合は必ずホスト公開鍵の指紋を確認したうえでログインするようにしてください (3.2.1. ホスト認証はなぜ必要か 参照)。
PuTTY でも認証エージェントがサポートされています。
使い方は簡単です。putty.exe
と同じフォルダ内に
pageant.exe
を置いておき、putty.exe
を起動する前にこれを実行するだけです。
pageant.exe
を実行すると画面右下のタスクトレイにアイコンが表示されます。
あとはこのアイコンを右クリックして表示されるメニューから「Add Key」を選択し、
秘密鍵ファイル (.ppk形式) を追加してください。
この後メニューから「New Session」を選択すると
putty.exe
が起動され、ログインの際に
自動的に認証エージェントと通信し公開鍵認証を行うようになります。
WinSCP [脚注: http://www.winscp.org/] は Windows 上で動く SFTP クライアントで、 エクスプローラ風の直観的なインターフェイスを備えています。 公開鍵認証には PuTTY の秘密鍵と同じ .ppk 形式の秘密鍵ファイルを使用するため、 シェルの使用は PuTTY で行い、ファイル転送は WinSCP を併用するといった 使い方に向いています。
WinSCP のログイン画面は PuTTY に似ています (図 winscp-login)。 ここでホスト名とポート番号およびユーザ名を入力したあと、 秘密鍵ファイルを指定して「Login」を押します。 パスフレーズが正しく入力されるとリモートのディレクトリが表示されます (図 winscp-file)。
Fugu[脚注: http://rsug.itd.umich.edu/software/fugu/]
は Mac OS X 上で動くファイル転送クライアントです。
これは内部で OpenSSH の sftp
プログラムを使用しており、
OpenSSH の秘密鍵ファイルやオプションなどもそのまま使えます。
また、ポート転送をおこなう機能もあります。
Fugu における認証方法は OpenSSH とまったく同じです。
公開鍵認証を使う場合は、あらかじめ OpenSSH の
ssh-keygen
コマンドで id_rsa
ファイル
(あるいは id_dsa
ファイル) を作成し、
ホームディレクトリの ~/.ssh/
以下に置いておきます。
なお、Mac OS X では秘密鍵・公開鍵ペアを生成したり、
秘密鍵のパスフレーズを変更するのに SSH Agent という
グラフィカルなツールを使うこともできます
(これも内部で OpenSSH を使っています)。
[脚注: http://www.phil.uu.nl/~xges/ssh/ ]
サーバに接続したあとは、Finder のウィンドウと同様に ドラッグ & ドロップでファイルを転送することができます。
ssh
コマンドにはさまざまなオプションがありますが、
これらを毎回いちいち指定するのは面倒です。
また、環境によっては異なるホストで別々のポート番号や
秘密鍵ファイルを使用しなければならないことがあり、
これらをすべて覚えておくことはユーザにとって負担です。
そのため OpenSSH では各ユーザが
ホスト名ごとに異なるオプションを記録する設定ファイルを作成することができます。
ssh
コマンドは与えられたホスト名によって
これらの設定を自動的に読み込み使用します。
ssh
コマンドの個人用設定は
クライアント上の ~/.ssh/config
というファイルに記録することが
決められています。~/.ssh/config
はテキストファイルであり、
以下に示すような形式になっています。
~/.ssh/config ファイルの例 |
---|
# univ. lab Host server.example.com Port 1729 ForwardX11 yes # my home server Host myhome HostName homeserver.example.net IdentityFile ~/.ssh/id_rsa_home User euske # common settings Host * Compression yes |
これは一般的なテキストエディタを使って変更します。 上の例を使うと、たとえば以下のようにタイプするだけで、 ユーザは斜体で書かれているコマンドと同等の結果を得られることになります。
実行例:
client$ ssh server.example.com … (ssh -p 1729 -X yusuke@server.example.com と同じ) client$ ssh myhome … (ssh -i ~/.ssh/id_rsa_home euske@homeserver.example.net と同じ) client$ rsync -a myhome:/home/yusuke/data . … (rsync が内部で呼びだす ssh にも同様のオプションが使われる)
~/.ssh/config
ファイルが便利なのは、単純にホスト名ごとの
異なるオプションを指定できるだけでなく、ホスト名の「エイリアス」を指定できることです。
上の例では ssh myhome
とタイプするだけで、実際には
homeserver.example.net
に接続でき、しかもログインするユーザ名まで指定できます。
さらにこのホスト名によるオプション指定は sftp
や rsync
を
使った場合でも有効です。
[脚注: これは sftp
や rsync
などのプログラムが
内部で ssh
コマンドを呼び出しているためです。]
このため複数のサーバにログインするような状況では、
多少時間をかけても ~/.ssh/config
ファイルを作成することは
十分に価値があります。
注意 |
---|
たとえホスト名のエイリアスを設定しても、OpenSSH 内部では
エイリアスは本物のホスト名に置換されています。
そのため known_hosts ファイルでは ssh で入力した名前ではなく、
HostName 設定項目で指定した本物のホスト名が使われます。
とくにハッシュ化された known_hosts ファイル (5.8.2. known_hosts ファイルの内容をハッシュ化する 参照) を
使っているときは known_hosts ファイルに格納されている名前と
ssh で入力した名前が異なるので注意が必要です。
|
~/.ssh/config
ファイルの文法
~/.ssh/config
ファイルの各行には、
1行にひとつの設定項目を記述します。
'#
' 以降はコメントとみなされます。
上の例では字下げは見やすさのためのものであり、実際には必要ありません。
各設定項目には "Host
" を指定するか、あるいは
表 config-options. に示す項目のどれかを指定します。
設定項目 | 機能 |
---|---|
Port ポート番号 |
接続するポート番号を指定する。(-p オプションに相当、4.1.3. 公開鍵認証でログインする 参照) |
User ユーザ名 |
ログインするユーザ名を指定する。(user@host の user部分に相当) |
HostName ホスト名 |
ログインするサーバのホスト名を指定する。(user@host の host部分に相当) |
IdentityFile 秘密鍵ファイル名 |
公開鍵認証に使う秘密鍵ファイルを絶対パス名で指定する。
そのユーザのホームディレクトリを表すのには ~ が使える。
(-i オプションに相当、4.1.3. 公開鍵認証でログインする 参照) |
ForwardAgent yes |
認証エージェントの転送を許可する。(-A オプションに相当、4.4.3. 認証エージェントを転送する 参照) |
ForwardX11 yes |
X11 転送を許可する。(-X オプションに相当、4.5. X11 転送を使う 参照) |
ForwardX11Trusted yes |
信頼された X11 転送を許可する。(-Y オプションに相当、4.5. X11 転送を使う 参照) |
Ciphers 暗号化方式1,暗号化方式2,... |
暗号化に使う方式を指定する。方式は複数個指定でき、最初に指定したものがもっとも優先して使われる。
なお、カンマの間にスペースを入れてはいけない。
[脚注: SSH1 プロトコルを使っている場合は Ciphers ではなく Cipher
という項目であり、指定できる暗号化方式は 1種類のみです。] |
Compression yes |
圧縮を有効にする。 |
HostKeyAlias ホスト名 |
ホスト公開鍵を検証するとき、ユーザが指定した名前のかわりに
このホスト名 でknown_hosts ファイルを検索する。(6.4.2. ポートを変えて複数のホストにログインする 参照) |
CheckHostIP no |
ホスト公開鍵を検証するとき、そのホスト名の IPアドレスで
known_hosts ファイルを検索するのを禁止する。
(6.4.2. ポートを変えて複数のホストにログインする 参照) |
Host
指定では、ssh
コマンドで指定する
サーバのホスト名を指定します。すべてのホストを指定するワイルドカード (*
) も
使用できます。~/.ssh/config
ファイルは、先頭の行から順に
読み込まれていきます。ある Host
指定が現れると、
それ以降の設定項目はすべてその Host
で指定された
ホスト名のみに適用されます。Host
指定がまだ一度もファイル中に
現れていないときや、Host *
が指定されているときは、
その設定項目はすべてのホスト名に対して適用されます。
Host 指定の適用範囲 |
---|
IdentityFile ~/.ssh/id_rsa_yusuke ] すべてのホストに適用される Protocol 2 ] # univ. lab Host server.example.com Port 1729 ] ホスト server.example.com に適用される ForwardX11 yes ] # my home server Host myhome HostName homeserver.example.net ] ホスト myhome に適用される IdentityFile ~/.ssh/id_rsa_home ] User euske ] # common settings Host * Compression yes ] すべてのホストに適用される |
なお、ssh
コマンドではシステム全体にわたる
設定ファイルもサポートされています。OpenSSH の設定ファイル用ディレクトリ
(/etc/ssh
など) にある ssh_config
設定ファイルには、
ssh
コマンドのデフォルトの設定項目が記述されています。
このファイルは OpenSSH をインストールした状態ではすべて
コメントアウトされていますが、~/.ssh/config
ファイルで
指定されていない設定項目については ssh_config
設定ファイルの値が使用されます。
また ssh
の -o
オプションを
使うことで、これらの設定項目をコマンドラインからじかに指定することも可能です。
設定項目をコマンドラインから指定する |
---|
$ ssh [-o設定項目1=値1] [-o設定項目2=値2] ... [その他のオプション] ... |
なお、表 config-options. に挙げた設定項目のうち
Ciphers
設定項目 と Compression
設定項目 をうまく使うと
遅いネットワーク接続での通信速度をやや向上させることができます。
具体的には Compression
設定項目で圧縮を許可し、
Ciphers
設定項目でなるべく高速な暗号化アルゴリズムを優先して
利用するようにします。
[脚注: 現在サポートされている暗号化アルゴリズムでは arcfour が一番速いようです。]
なお、実際に圧縮が有効になるかどうかや、どの暗号化アルゴリズムが使われるかはサーバ側の
設定にも依存するため、クライアント側でこれらの設定を変更したからといって
必ずしもつねに通信が速くなるとはかぎりません。
注意 |
---|
Ciphers 設定項目で設定する暗号化アルゴリズムの数は減らさないようにしてください。
相手の SSH サーバのバージョンによっては、blowfish や arcfour などの
暗号化アルゴリズムはサポートされていないことがあります。
その場合、Ciphers に使用可能な暗号化アルゴリズムが含まれていないと
ssh コマンドは "no matching cipher found " という
エラーを出して終了してしまいます。
|
高速な暗号化アルゴリズムと圧縮を使用する |
---|
Compression yes Ciphers arcfour,blowfish-cbc,aes128-cbc,cast128-cbc,aes192-cbc,aes256-cbc,3des-cbc |
コラム - OpenSSH を使ってもパスワードは推測される |
---|
どんなに OpenSSH で通信内容を暗号化したところで、
「通信をしている」という事実自体は隠すことができません。
とくにユーザがシェルを使う OpenSSH では、
TCP/IP パケットの流量からユーザのキーの打鍵間隔が
推測できてしまいます。また、OpenSSH のパスワード認証では
入力したパスワードは一度にサーバに送られますが、古いバージョンの SSH では、
「パスワードが 4文字以下の場合は 1パケットで送られるので、
それが 4文字以下であることが外部にバレてしまう」という欠陥がありました。
カリフォルニア大学バークレー校の Songらによる研究では、
たとえユーザが OpenSSH を使っていても、打鍵間隔の測定によって
実際にパスワードの推測範囲を大幅に狭められることがわかっています。
ユーザが OpenSSH でサーバにログインし、
そこで このことを考えると、たとえ OpenSSH を使っていても、 ネットワークを経由したパスワード入力はなるべく避けたほうがよさそうです。 参考文献: Dawn Xiaodong Song, David Wagner and Xuqing Tian, "Timing Analysis of Keystrokes and Timing Attacks on SSH", USENIX Security Symposium, 2001. |