UNIX/Linuxの部屋 sshコマンドの使い方

TOP UNIX/Linuxの部屋 UNIX/Linuxコマンド一覧 用語集 新版 由来/読み方辞書 環境変数マニュアル Cシェル変数 システム設定ファイル システムコール・ライブラリ ネットワークプログラミングの基礎知識 クラウドサービス徹底比較・徹底解説




コマンド ssh SSH サーバにリモートログインする (OpenSSH) このエントリーをはてなブックマークに追加

最終更新


UNIX/Linux の ssh コマンドはリモートのサーバにログインするためのコマンドである。ssh プロトコルを用いているので、やりとりは暗号化されており安全である。本ページでは OpenSSH 同梱の ssh コマンドについて説明する。


ssh 接続時の前提
ssh コマンドはクライアントプログラムである。接続先に sshd デーモンが起動していなくてはならない。また、無事ログインするためには接続先にアカウントが作成されており、そのパスワード等を把握している必要がある。

ssh コマンドの基本的な使い方
ssh コマンドの基本的な使い方を解説する。

ログインする場合は下記のようにする。2つの書き方があるが、どちらでも同じである。
% ssh -l [ユーザ名] [ホスト名またはIPアドレス]
% ssh [ユーザ名]@[ホスト名またはIPアドレス]

もし、ローカルとリモートのユーザ名 (id コマンドで表示されるもの) が同じであるなら、下記のようにユーザ名を省略してもよい。
% ssh [ホスト名またはIPアドレス]

ログインではなく、リモートサーバでコマンドを実行するだけの場合は、下記のように最後の引数に実行したいコマンドを指定する。
% ssh -l [ユーザ名] [ホスト名またはIPアドレス] [コマンド]
% ssh [ユーザ名@][ホスト名またはIPアドレス] [コマンド]
こちらもリモートのユーザ名は省略可能である。その場合ローカルのユーザ名が使われる。
% ssh [ホスト名またはIPアドレス] [コマンド]
例:
% ssh myuser@remoteserver ls
→ remoteserver に myuser で認証し、ls コマンドを実行する。

ssh 経由で複数のコマンドを実行する
ダブルクォートで囲んで、セミコロンや "&&" などを用いて複数のコマンドを記述すればよい。
% ssh remotehost "ls; cal"
% ssh remotehost "cd /foo/bar && mycommand"

また、標準入力から任意コマンドを流しこむことも可能である。
% (echo ls; echo cal) | ssh remotehost

ssh 経由で実行したコマンドの終了ステータスを取得する
ssh コマンドは、ssh 経由で実行した最後のコマンドの終了ステータスを返してくれるので、普通に $? などを参照すればよい。
% ssh remotehost "ls"
% echo $?
→ おおむね正常終了を表す 0 が取得できる
% ssh remotehost "ls no-exist.txt"
% echo $?
→ 存在しないエラーを ls したので、エラーを表す 1 が取得できる

ssh 経由で tar や tar.gz ファイルを転送する
バックアップ用途でローカルのファイル群をリモートに転送する、またはその逆を行いたいことがある。

もちろん tar + gzip 等でアーカイブを作成し、scp コマンド転送してもよいのだが、
  • 一時ファイル作成のためにディスク容量を使わせたくない
  • 無駄なディスク I/O を発生させたくない
という理由がある場合など、ssh にパイプ経由で転送する方法を紹介する。

▷ ローカルからリモートへ
tar で mydir/ 以下をアーカイブし、アーカイブのままリモートに保存:
% (tar cf - mydir) | ssh -l [ユーザ名] [リモートサーバ名] "cat > backup.tar)
gzip で圧縮:
% (tar zcf - mydir) | ssh -l [ユーザ名] [リモートサーバ名] "cat > backup.tar.gz)
bzip2 で圧縮:
% (tar jcf - mydir) | ssh -l [ユーザ名] [リモートサーバ名] "cat > backup.tar.bz2)
tar + gzip で転送し、コピー先で展開:
% (tar zcf - mydir) | ssh -l [ユーザ名] [リモートサーバ名] "cd foo/bar/ && tar xf -)
▷ リモートからローカルへ:
リモートで tar でアーカイブし、アーカイブのままルーカルに保存:
% ssh -l [ユーザ名] [リモートサーバ名] 'cd foo/bar/ && tar cf mydir' > backup.tar
gzip で圧縮:
% ssh -l [ユーザ名] [リモートサーバ名] 'cd foo/bar/ && tar zcf mydir' > backup.tar.gz
bzip2 で圧縮:
% ssh -l [ユーザ名] [リモートサーバ名] 'cd foo/bar/ && tar jcf mydir' > backup.tar.bz2
リモートで tar + gzip でアーカイブし、ルーカルで展開:
% ssh -l [ユーザ名] [リモートサーバ名] 'cd foo/bar/ && tar zcf mydir' | tar xf -

ssh コマンドのオプション
ssh コマンドのオプションを以下に示す。

▷ -l [ユーザ名]
リモートログイン先のユーザ名を指定する。
▷ -p [ポート番号]
リモート接続する際の、リモート側のポート番号を指定する。通常はポート 22 だが、ポートスキャンを回避するためにポート番号 10022 としていたり、別ポートで別の SSH サーバを立ち上げている場合があるので、そのようなときに使う。
% ssh remote.example.com -p 10022
→ ポート 10022 に接続
▷ -i [ファイル名]
公開鍵認証方式における秘密鍵ファイルを指定する。デフォルトでは下記が使用される。
  • ~/.ssh/id_rsa
  • ~/.ssh/id_dsa
  • ~/.ssh/id_ecdsa
  • ~/.ssh/id_ed25519
▷ -C
通信データの圧縮を行う。デフォルトでは圧縮は行わない。なお、「通信経路が遅い」「ローカル/リモートの CPU が高速」という条件が揃わないとむしろ遅くなることもある。
▷ -c
通信の暗号化方式を指定する。OpenSSH 標準では下記の優先順位で使用されると思われる。速度アップ目的であれば arcfour 系にするのはひとつの手かもしれない。
  • aes128-ctr
  • aes192-ctr
  • aes256-ctr
  • arcfour256
  • arcfour128
  • aes128-cbc
  • 3des-cbc
なお、SSH においては、セッション鍵と呼ばれる AES や 3DES などの共通鍵暗号方式にてデータの暗号化が行われている。RSA や DSA 等の公開鍵方式は、接続時の初回にセッション鍵を安全に受け渡すための方法である。よって、-c オプションでの暗号化方式は、接続スピードに大きな影響を与える。
▷ -o オプション
ssh のオプションを設定する。下記のように使用する。
% ssh -o [オプション名]=[値] [リモートサーバ] ...
例: known_hosts のチェックを省略する場合
% ssh -o StrictHostKeyChecking=no [リモートサーバ]

なお、この設定を常に有効化したい場合は ~/.ssh/config に記載する。また、サーバ全体で共通デフォルト設定としたい場合は /etc/ssh/ssh_config に記述することもできる。

設定可能な項目は man ssh_config を参照。

OpenSSH に含まれるコマンド一覧
OpenSSH に含まれるコマンドを説明する。

▷ 主にクライアント側として使うコマンド:
  • ssh コマンド
リモートログイン、リモートでのコマンド実行を行う。
  • ssh-keygen コマンド
公開鍵や秘密鍵を生成、管理する。
  • ssh-agent コマンド
公開鍵暗号方式において、秘密鍵を管理する。パスフレーズの入力を一度で済ませるためのツール
  • ssh-add コマンド
公開鍵暗号方式において、秘密鍵を管理する。パスフレーズの入力を一度で済ませるためのツール
  • ssh-copy-id コマンド
ssh-keygen で作成した公開鍵を、リモートサーバに簡単にコピーするためのコマンド。
  • ssh-keyscan コマンド
known_hosts 更新を効率化するためのコマンド。サーバ追加や鍵変更時の更新作業を便利にするツール。
  • scp コマンド
ファイルをローカル・リモート間でコピーする。内部的には ssh コマンドを叩いている。
  • sftp コマンド
FTP と似たようなコマンドが使えるが、内部的には ssh プロトコルで動いている。

▷ 主にサーバ側として使うコマンド:
  • sshd コマンド
ssh や scp などの相手をする ssh サーバプログラム
  • sftp-server コマンド
sftp サーバプログラムとして昔から存在したが、今は internal-sftp を使えばよいので使うことはないと思われる。sftp-server だと chroot できないという欠点もある。
  • scponly コマンド
scp でファイルのコピーはさせたいが、ssh でログインさせたくないというニーズに対応するためのコマンドとして、scponly が配布されていた。scponly をログインシェルに設定していたわけである。2019年現在では OpenSSH 単体で、scp のみ・sftp のみという設定ができるので、scponly を使うケースはないと思われる。なお、scponly は OpenSSH プロジェクトの配布物ではない。

初回接続時の警告
リモートサーバに初めて接続した場合、下記が表示される。これは接続先のサーバが正しいサーバであるか、DNS スプーフィングなどの攻撃により、本来接続すべきでないサーバに接続していないかを確認するためのものである。
% ssh first-connect.example.com
The authenticity of host 'first-connect.example.com (111.222.33.44)' can't be established.
RSA key fingerprint is SHA256:Vr9lAsKbyVJzqyHqrRCBlm9+vzCb+pPU+Lz9LHO8i7M.
No matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)?

ここで yes とすると ~/.ssh/known_hosts に追加され、次回以降は表示されなくなる。
初回ログイン時の確認をきっちりやるならば、あらかじめリモートサーバ管理者がリモートサーバにて下記のようにホスト鍵の finger print を表示する。
% ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub
2048 SHA256:ALJaskKsMzl98a1laFt2FzJlKliKkFtEs20dsIWU9PA root@first-connect.example.com (RSA)
これをメールや印刷物など何らかの手段で新規ログインする人に伝え、
「初回接続時に表示された finger print が一致しない場合、ログインせずすぐに連絡すること」
と指示すべきである。しかしながら当ページ管理人のヌルい環境では、そのような運用を見たことはない。

なお、DNS スプーフィングや中間者攻撃により攻撃者のサーバに接続した場合や、リモートサーバが OS 再インストールされてホスト鍵の内容が変わった場合は
「過去の接続時と finger print が異なる!」
という警告が表示される。

もしこのホスト鍵の finger print チェックを一切行わない場合は、ssh 実行時の引数に -o "StrictHostKeyChecking no" を付けるとよい。また、下記で ~/.ssh/known_hosts より該当ホスト名のエントリを削除する手もある。
% ssh-keygen -R [ホスト名]

パスワードなしでログイン・コマンド実行する
定期実行などでパスワードなしでログインする場合、下記のようにする。
  • パスワード認証を使わず、公開鍵認証を使う
  • 秘密鍵にパスフレーズをつけない (ssh-keygen 生成時に Enter passphrase と聞かれる際、何も入力せず Enter を押下する)

なお、ホストベース認証を使う手もあるが、推奨はされない。

パスワード認証と公開鍵認証とパスフレーズ
ssh ではパスワード認証と公開鍵認証という 2つの認証方式がある (実際はホストベース認証とか、ワンタイムパスワード認証もあるが省略)。

パスワード認証は、ログイン先のアカウントに登録されたパスワードでログインするもの。このパスワードとは、passwd コマンドで変更したり、/etc/shadow や /etc/master.passwd にハッシュ化されたものが記載されている、アレのことである。

公開鍵認証とは、ログイン先のアカウントに登録されたパスワードは一切関係ない。例えば RSA という方式であれば、乱数を用いて大きな素数を 2つ (n と m) 求めて、それをかけた数 (n×m) が公開鍵。2つの素数が秘密鍵。ログイン先に公開鍵を配置し、手元に秘密鍵を置いておく。

ややこしいのが、公開鍵暗号方式においてはパスフレーズという概念があること。そもそも公開鍵認証においては人間の頭の中にあるパスワード文字列的な概念は存在しない。長い桁数の素数を知っているかのみがキモである。

ただ、秘密鍵は普通にファイルとして保存されている。パーミッションを設定して誰でも見られないようになっているけれども、セキュリティホールを付かれて root 権限が奪われたなら、接続先にログインしたい放題である。

これでは困るので、秘密鍵を暗号化して保存することができる。暗号化・復号化においてはパスワードが必要であるが、これは操作者の頭の中だけにあって、秘密鍵を暗号化・復号化する際には都度パスワードを入力しないといけない。

この「パスワード認証」と「公開鍵認証方式における秘密鍵ファイルを暗号化・復号化するときに使用するパスワード」が極めてわかりづらいので、ssh において後者には「パスフレーズ」という似て非なる名前をつけた、ということである。

ssh 公開鍵認証方式における公開鍵の設置方法
ssh 公開鍵認証方式を成功させるには、下記が必要である。
  • ローカルに ~/.ssh/id_rsa という秘密鍵ファイルが存在する。
  • リモートの ~/.ssh/authorized_keys に、秘密鍵に対応する公開鍵を登録する。

「まだ一度もログインしていないんだから、リモートの ~/.ssh/authorized_keys に追加できないのでは?」と思うかもしれないが、それは大正解である。ssh 公開鍵認証のみが許されている状況で、リモートに公開鍵を未登録であるならば、どうやってもログインできない。

よって下記のいずれかが必要である。
  • 最初はパスワード認証でログインし、~/.ssh/authorized_keys に公開鍵を登録し、次回からは公開鍵認証でログインする。
  • 自身の公開鍵 (~/.ssh/id_rsa.pub など) をリモートサーバの管理者にメール等で渡し、~/.ssh/authorized_keys にあらかじめ追加してもらう。

ssh 公開鍵と秘密鍵の中身を確認する方法
openssl コマンドを使うと、ssh 秘密鍵の内容を確認できる。下記例の prime1 と prime2 が素数である。
% openssl rsa -in ~/.ssh/id_rsa -text
(略)
prime1:
00:fe:04:1d:8a:50:b9:9a:84:e6:b1:45:d2:0f:8f:
(略)
50:79:fb:6c:4a:04:3f:52:c5
prime2:
00:fc:98:c0:75:8a:0e:98:93:9c:fc:c4:9a:d8:85:
(略)
54:d2:cf:33:30:df:c9:e2:b1
ちなみに 2018/8 リリースの OpenSSH 7.8 より ssh-keygen の生成する秘密鍵について、デフォルトフォーマットが PEM から OpenSSH 独自フォーマットに変更となった。上記の ~/.ssh/id_rsa はそれ以前のバージョンで作成したので openssl コマンドで内容表示できたが、OpenSSH 7.8 以降の ssh-keygen を使う場合、下記のように "-m PEM" を付けて生成してほしい。
% ssh-keygen -t rsa -m PEM

一方、公開鍵の内容を確認するには下記のようにする。2行目の FAA… が prime1 と prime2 の積である。ssh-keygen コマンドが含まれる OpenSSH のバージョンが古いと、-m オプションがないと言われるかもしれない。
% ssh-keygen -f ~/.ssh/id_rsa.pub -e -m pem | openssl asn1parse
    0:d=0  hl=4 l= 266 cons: SEQUENCE
    4:d=1  hl=4 l= 257 prim: INTEGER     :FAA39E7D6(略)6E872435
  265:d=1  hl=2 l=   3 prim: INTEGER     :010001

下記は、秘密鍵から prime1 を取得し、改行コードやコロンの除去、英字を大文字化して、prime1.txt に保存する。同様に prime2 も prime2.txt に保存する。それを bc コマンドを使って「prime1 × prime2」を求める。
% openssl rsa -in ~/.ssh/id_rsa -text | perl -pe '$_=join("",<>);($_)=m/prime1:(.*)prime2:/sm;s/[\n: ]//g;tr/a-f/A-F/' > prime1.txt
% openssl rsa -in ~/.ssh/id_rsa -text | perl -pe '$_=join("",<>);($_)=m/prime2:(.*)exponent1:/sm;s/[\n: ]//g;tr/a-f/A-F/' > prime2.txt
% (echo "obase=16;ibase=16" ; echo `cat prime1.txt`"*"`cat prime2.txt` ) | bc

結果は "FAA39E7D6…" と、~/.ssh/id_rsa.pub で確認したものが表示されるはずである。

id_rsa という秘密鍵には素数が 2つ、id_rsa.pub という公開鍵には素数の積が入っていることを実感いただけると幸いである。2つの素数をかけた公開鍵から、元の素数を求めることは非常に難しい。もしこれが実現できたら世界中が大騒ぎとなる。

一方、秘密鍵には素数が 2つそのまま格納されているので、掛け算で公開鍵を求めることは非常に簡単である。なので、公開鍵は公開してもよく、秘密鍵は公開してはならない。そして秘密鍵には素数そのものが書いてあるので、AES256 などでパスフレーズをかけたくなる気持ちも理解いただけただろうか。

公開鍵暗号方式で使用する公開鍵アルゴリズム (RSA・DSA・ECDSA・ED25519)
公開鍵暗号方式と言えば RSA が有名であるが、RSA 以外にも公開鍵暗号方式に使えるアルゴリズムが存在する。

ssh-keygen コマンドで公開鍵暗号を作成する際、デフォルトでは RSA が使用されるが、オプションで "-t dsa" などとすることで、RSA 以外の鍵を生成することも可能である。使用可能な代表的な公開鍵暗号アルゴリズムは以下のとおり。
  • rsa: 大きな素数の素因数分解が困難であることをベースとしたアルゴリズム
  • dsa: デジタル署名アルゴリズム。
  • ecdsa: 楕円曲線 DSA
  • ed25519: エドワーズ曲線デジタル署名アルゴリズム

一般的には rsa<dsa<ecdsa<ed25519 の順で高速かつサイズが小さいとされている気がするが、当ページ管理人はタイプがめんどくさいので RSA を使っている。

ちなみに ed25519 は、2^255-19 という素数をベースとした楕円曲線をベースとしているためこのような名前になっている。メールサーバ qmail などを開発した暗号学者 djb 氏が率いるチームが発見したアルゴリズム。

ssh で多要素認証 (MFA)
ssh では、多要素認証が可能である。
  • パスワード認証と公開鍵認証方式
  • 公開鍵認証と Google Authenticator (スマホアプリでの認証)

詳細はいつか書く。

ssh の歴史
1995年以前、rsh・rlogin・telnet などのリモートログインできるツールは存在したが、これらには暗号化機能が実装されておらず、ネットワークの盗聴には無力であった (パケットを盗聴されていれば、ログイン ID もパスワードも、コマンド実行結果もすべて取得できた)。

1995年、ヘルシンキ大学の Tatu Yolen 氏が、通信路を暗号化する ssh プロトコルを考案し、ssh クライアント・サーバの実装を行い、ssh として発表した (ssh-1)。この時点では無償で使うことができ、皆 rsh や telnet を捨て、ssh に移行しはじめていた。

その後 ssh-v1 には脆弱性が発見され、よりセキュアな ssh-v2 プロトコルが考案され、ssh-2 がリリースされた。しかしこの時点で有償化されたような気がする (多分)。オープンソース・フリーソフトウェア界隈は、脆弱性のない ssh を使うことができなくなり困っていた。

1999年に OpenBSD プロジェクトにおいて、オープンソースであった ssh-1 をベースとした OpenSSH がリリースされ、脆弱性のない ssh を無償で使うことができるようになった。

2019年現在、FreeBSD や Linux など、オープンソース界隈で使われているのは OpenSSH の方であるが、有償サポートが必要な場面においては、SSH Communication Security 社 (Tatu Yoken 氏が設立した会社) の SSH Tectia Server が使われることがあるかもしれない。

SSH と SSL の関係性
SSH と SSL (TLS) は名前が似ているので、初心者はどのような関係があるのか混乱するかもしれない。なおかつ OpenSSH と OpenSSL というこれまた似た名前のパッケージがあるためややこしい。

結論から言うと、SSH と SSL は全く別の規格であるが、ベースとなっている暗号技術や使われ方に共通点があるので、全くの無関係というわけでもない。

- SSH SSL
主な使われ方 リモートログイン・リモートコマンド実行 ブラウザと Web サーバ間の暗号化
その他の使われ方 scp, sftp FTPS, SMTPS, POP3S, DNS over TLS など
ポート番号 22 443
公開鍵認証方式 使えるが、パスワード認証・ホストベース認証なら使わない 使う
共通鍵認証方式 (AES など) 使う 使う
認証局 元々は認証局は存在しない。2015年頃、SSH CA 認証なるものが出てきたが、まだ一般的ではない ベリサイン等、多くの認証局がある

関連コマンド
>> FreeBSDオンラインマニュアル(man) FreeBSD ssh(1)