未経験からサーバーエンジニアに転職するために勉強しています。一番理解が進んだ分野がssh接続なので、勉強した結果をアウトプットするため本記事を作成しました。私と同じような初心者エンジニアの方達の手助けとなれば幸いです。
実行環境
クライアント : Mac OS Ventura ver13.0
仮想マシン : VirtualBoxバージョン 7.0.4 r154605 (Qt5.15.2)
ゲストOS(サーバ): CentOS Linux 7 (Core)
1. sshとは
sshとは「Secure SHell」の略で、離れた場所にある別のコンピューターを、ネットワーク経由で遠隔操作するための方法です。リモートでサーバーの内部を操作したり、ファイルの送受信を行ったりする事が出来ます。
sshを用いれば、パスワードを含む全ての通信内容は暗号化されるので、通信経路上における盗聴やデータの改ざんを防ぎ、安全に遠隔操作を行うことが出来ます。
2. sshの認証方法(公開鍵認証)の概要
離れた場所にあるサーバーへ安全に接続するため、sshは複雑にできています。さらに、サーバーへのログインが適正かどうかチェックする認証方法は、複数用意されています。
代表的なものには「パスワード認証方式」と「公開鍵認証方式」の2つあり、sshの設定方法により選択可能となっています。
「公開鍵認証方式」はいくらか初期設定作業が必要ですが、「パスワード認証方式」と比べ通信の安全性はより高いとされています。
「鍵」と呼ばれるファイルをしっかり保管さえすれば、「鍵」のないユーザーからのログインは原則できません。これにより、悪意をもった第三者からの不正なログインを防ぐことができます。
3. 公開鍵認証方式における注意点
公開鍵方式では「公開鍵」と「秘密鍵」の2種類の鍵を使って認証を行います。sshの場合はパスワードの代わりに秘密鍵を用いる感覚で使うことができます。もちろん、パスワードと同じように秘密鍵は厳重に管理する必要があります。
秘密鍵はファイルとしてクライアント側(自身のコンピュータ)に残すことが前提となっているので、秘密鍵が漏洩するリスクがパスワードが漏洩するリスクに比べて高いという点があります。しかし、このデメリットは、秘密鍵自体にパスワードを設定することで打ち消すことが出来ます。
つまり、秘密鍵を使用するためにはパスワードを入力する必要があるように設定します。これはいわば従来のパスワード認証と公開鍵認証の良いとこ取りをしたような形になりますので、ここではこの方式の設定方法を紹介していきます。
4. sshを利用するための準備物
クライアント側(自身のコンピュータ):sshクライアント
遠隔からコンピュータに接続して操作するクライアント側のソフトウェア。sshサーバと通信し、利用者の操作を受け付けてサーバに伝達したり、サーバからの応答を表示します。
サーバ側(接続先のコンピュータ):sshサーバ
sshサーバとは、遠隔からコンピュータに接続して操作するサーバ側のソフトウェア。sshクライアントと通信し、利用者の操作を受け付けて実行し、結果をクライアントに応答します。
なお、sshクライアント・sshサーバの具体的な実装としてはOpenSSHがよく用いられ、LinuxなどのUNIX系OSの多くに同梱され標準的に用いられています。また、MAC OS X以降、Windows 10以降には標準でOpenSSHがインストールされているので、通常ではインストールする必要はありません。
5. 公開鍵認証によるssh接続の手順
パスワード認証方式でログイン出来ることを確認
クライアント側で以下のコマンドを実行して、パスワード認証方式でsshサーバーにログインできることを確認します。
$ ssh <ユーザ名>@<SSHサーバーのIPアドレス>
もし下記のエラーが出てパスワード認証方式でログインできない場合は、パスワード認証が許可されていないケースが考えられます。
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
パスワード認証方式でSSH接続を試みて上記のエラーが出た場合は、サーバ側のファイル /etc/ssh/sshd_config の記述を確認してみましょう。
ルート権限でログインします。
# vi /etc/ssh/sshd_config
`PasswordAuthentication no`の部分を`PasswordAuthentication yes`に変更
:wqコマンドで保存終了します。
# service sshd restart 変更を反映させます。
公開鍵と秘密鍵の生成
~ $ cd .ssh .ssh ディレクトリへ移動
.ssh $ ssh-keygen -t ed25519 公開鍵と秘密鍵を作成
ssh-keygen コマンドの -t オプションで鍵の種類 ed25519 を指定します。種類を指定しない場合は、デフォルトでは rsa が生成されますが、より強固で鍵の生成が速い ed25519 を選択します。- SSH は (RSA 鍵より) ED25519 鍵の方が強固で速い
ed25519 に対応していない古い ssh の実装で rsa を使用する場合は、より強固にするために-bオプションで4096bitの鍵長を指定すると良いでしょう。
.ssh $ ssh-keygen -t rsa -b 4096 公開鍵と秘密鍵を作成
ssh-keygenコマンドを入力後、秘密鍵の保存場所と秘密鍵に設定するパスワードを入力します。
鍵の保存場所と名前を指定
Generating public/private ed25519 key pair.Enter file in which to save the key (/Users/yourname/.ssh/id_ed25519): mykey[秘密鍵の保存場所と名前を指定]
鍵は慣習的に ~/.ssh 下に入れることが多いため、今回は鍵の名前 mykey だけ指定します。
ここで指定するのは秘密鍵のファイル名であり、公開鍵のファイル名は秘密鍵のファイル名に .pub がついたものになります。
秘密鍵に設定するパスフレーズを入力(忘れないよう覚えておきましょう)
Enter passphrase (empty for no passphrase): [パスフレーズ] パスフレーズを設定してください。
Enter same passphrase again: [パスフレーズ] もう一度同じパスフレーズを入力してください。
パスフレーズを指定しなくても秘密鍵を生成することは可能ですが、秘密鍵が流出した場合はそのままssh接続されてしまいます。
パスフレーズを指定しておけば、ssh接続する際にパスフレーズの入力を求められるのでより安全です。セキュリティを強固にするためパスフレーズを指定します。パスフレーズとは?パスワードとの違い・作り方のポイントを紹介!
パスフレーズ入力後に以下のようなメッセージが表示されて、鍵の生成が終了します。
Your identification has been saved in :鍵の場所・名前
Your public key has been saved in :鍵の場所・名前
The key fingerprint is:
SHA256:ランダムな英数字
The key's randomart image is:
+--[ED25519 256]--+
| ......... |
| ........ |
| ......... |
| .............. |
| ...... |
| ... |
| ......... |
| .... |
| ...... |
+----[SHA256]-----+
以下のコマンドを入力して、出力結果に2つの鍵が含まれていれば作成成功です。
.ssh $ ls .ssh
mykey mykey.pub
mykey はssh接続する際に使用する秘密鍵です。このファイルは利用者だけが持つべきもので、外部に公開してはいけません。対して、 mykey.pub は公開鍵です。このファイル内の情報を接続先サーバーに登録して、公開鍵認証を行うことになります。
サーバ側(接続先)の .ssh ディレクトリを確認
※ この部分は ssh-copy-id コマンド(後述)で省略可能
サーバ側のホームディレクトリ以下に .ssh ディレクトリがあるか確認しておきましょう。加えて .ssh ディレクトリのパーミッションが 700 であるか確認してください。
なお、パーミッションが正しく設定されていない場合は「Permission denied」となり、ssh接続が出来ないので、パーミッションを変更してください。→ Permission denied (publickey,gssapi-keyex,gssapi-with-mic)
$ cd ホームディレクトリへ移動
~ $ ls -a
.ssh .sshディレクトリがある事を確認
~$ cd .ssh .sshディレクトリへ移動
.ssh $ ls -ld
drwx------ 2 xxxx xxxx 6 JAN 5 22:24 パーミッション(700)を確認
サーバ側のホームディレクトリ以下に .ssh ディレクトリがない場合は以下のコマンドで作成してください。
$ cd ホームディレクトリへ移動
~ $ mkdir .ssh .ssh ディレクトリを作成
.ssh ディレクトリのパーミッションを 700 に変更するためには、以下のコマンドを使用してください。
$ cd ホームディレクトリへ移動
~ $ chmod 700 .ssh パーミッションを変更
公開鍵をサーバ側に登録
※ この部分は ssh-copy-id コマンド(後述)で省略可能
サーバにssh接続をするためには、事前にクライアントが上記で作成した公開鍵をサーバに登録しておく必要があります。ここでは scp コマンドを使用して、パスワードを用いた ssh 接続で公開鍵ファイルをサーバーに送信することとします。
$ scp ~/.ssh/mykey.pub[接続先サーバのユーザー名]@[接続先サーバのIPアドレス]:~/.ssh
$[接続先サーバのユーザー名]@[接続先サーバのIPアドレス]'s password:[接続先サーバのログインパスワード]
mykey.pub 100% 124 133.8KB/s 00:00
scp コマンドにより、サーバ側の .ssh ディレクトリ下に公開鍵 mykey.pub が送信されました。
サーバ側に scp コマンドで送った公開鍵 mykey.pub が登録されているか確認してみましょう。
~ $ cd .ssh .sshフォルダに移動
.ssh $ ls
mykey.pub .ssh フォルダ内に公開鍵 mykey.pub があれば成功です。
この公開鍵の中身を cat コマンドで authorized_keys ファイルに追記してください。公開鍵の中身を authorized_keys に追記以降は、 mykey.pub を使用しないので、rm コマンドで削除します。
.ssh $ cat mykey.pub >> authorized_keys | rm mykey.pub
上記のコマンドにより authorized_keys ファイルが作成され mykey.pub の内容が追記されます。
.ssh $ ls
authorized_keys
所有者以外に不要なパーミッションを付与するとssh接続が失敗してしまうため、 authorized_keys のパーミッションを 600 に変更します。
.ssh $ chmod 600 ~/.ssh/authorized_keys
scpコマンドは ssh-copy-id コマンドでも代用可能です。
ssh-copy-id コマンドは
・サーバ側で .ssh ディレクトリの作成
・サーバ側で作成した .ssh ディレクトリのパーミッションを 700 に変更
・クライアント側からサーバ側へ公開鍵の送信
・サーバ側に送信された公開鍵を authorized_keys へコピー
・サーバ側に送信された公開鍵の削除
・authorized_keys のパーミッション変更
以上を自動で行ってくれます。
ssh-copy-id コマンドにより、本記事で記載している手順3と手順4の部分が自動化され、大変便利です。手間を省き設定ミスを減らすために ssh-copy-id コマンドを推奨します。
公開鍵・秘密鍵ペアを作成後、実際に ssh-copy-id コマンドを使用してみましょう。
↓↓↓
.ssh $ ssh-copy-id -i ~/.ssh/<生成した公開鍵ファイル名> <接続先のユーザー名>@<接続先のIPアドレス>
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/Users/クライアントユーザー名/.ssh/公開鍵"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
[接続先サーバのユーザー名]@[接続先サーバのIPアドレス]'s password:[接続先サーバのログインパスワード]
Number of key(s) added: 1
Now try logging into the machine, with: "ssh '[接続先サーバのユーザー名]@[接続先サーバのIPアドレス]'"
and check to make sure that only the key(s) you wanted were added.
公開鍵認証でssh接続する
上記1~4の手順の通りで、公開鍵認証によるssh接続するための作業は終わりです。秘密鍵のパスフレーズを入力して、クライアント側から接続先サーバにログインできるかどうか確認してみましょう。
※ログイン時は、-i オプションでログイン時に使用する秘密鍵を指定しましょう。-i オプションを追記しない場合は「パスワード認証方式」でログインしてしまいます。
$ ssh -i ~/.ssh/[秘密鍵ファイル名][接続先サーバのユーザー名]@[接続先サーバのIPアドレス]
Enter passphrase for key '~/.ssh/[秘密鍵ファイル名]':[秘密鍵のパスフレーズ]
パスフレーズ入力後、下記の表示があればサーバ側にログイン成功です。
Last login: Sat Jan 2 18:29:50 2023 from 192.168.xxx.xxx
[user@centos7 ~]$
6. ssh接続をよりセキュアにするために
パスワード接続を無効にする
公開鍵認証によるssh接続に成功した後は、パスワードによるssh接続を無効にしてセキュリティを高める方が良いでしょう。パスワードはユーザーが作成するので、保証できる強度の程度が低いためです。
root権限でのログインを禁止する
ssh接続でいきなりroot権限での接続は望ましくありません。Linuxサーバーであれば、通常rootが管理者権限を持ったユーザーとして用意されており、攻撃者はとりあえずrootでログインできないかどうか試してくるためです。rootによる直接なログインを禁止しておくと良いでしょう。-rootログインを禁止する
ポート番号を変更する
ssh接続はデフォルトだとポート番号は”22”になっています。インターネットでは全世界の22番ポートをくまなく調べて、セキュリティホールのあるサーバーが無いかチェックしている危ないロボットがいるそうです。
こうした無差別攻撃を防ぐために、ウェルノウンポート以外の任意の番号(1024~66535の任意の番号)に設定しましょう。-【ssh】ポート番号を変更しよう
上記1~3の設定を行うために、接続先サーバにてsshの設定ファイル /etc/ssh/sshd_config を編集しましょう。
root権限で設定します。
# vi /etc/ssh/sshd_config
`PermitRootLogin yes`部分を`PermitRootLogin no`に変更
`PasswordAuthentication yes`部分を`PasswordAuthentication no`に変更
`#Port 22`の行頭#を削除し`Port 1024~66535の任意の番号`に書き換える
:wqで保存終了
上記の内容で編集後、sshdを再起動して変更を反映させましょう。
ルート権限で再起動します。
# service sshd restart
Redirecting to /bin/systemctl restart sshd.service
firewalldの設定変更(CentOS 7を利用している場合)
firewalld は、CentOS 7 から採用された、通信の許可/拒否を制御するパケットフィリタリングの仕組みのことです。
firewalld では、通信の許可/拒否についてあらかじめルールを設定しておく必要があります。 /etc/ssh/sshd_config のポート番号変更に伴い、以下の通りfirewalld も設定を変更しましょう。-CentOS7(firewalld)-SSHのポート番号を変更する
まずは firewalld の設定ファイルのひな形を /etc/firewalld/services/ にコピーします。
ルート権限で設定します。
# # cp /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services/
設定ファイル /etc/firewalld/services/ssh.xml に記述されているポート番号22を /etc/ssh/sshd_config で設定した任意のポート番号へ修正します。
ルート権限で修正します。
# vi /etc/firewalld/services/ssh.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>SSH</short>
<description>Secure Shell (SSH) is a protocol for logging into and executing commands on remote machines. It provides secure encrypted communications. If you plan on accessing your machine remotely via SSH over a firewalled interface, enable this option. You need the openssh-server package installed for this option to be useful.</description>
<port protocol="tcp" port="22"/> この行のポート番号を書き換えましょう。
</service>
ポート番号の修正後は、 firewall-cmd で変更した設定を反映しましょう。
ルート権限で設定します。
# firewall-cmd --reload
success
success と表示されれば firewalld の設定変更は成功です。
接続元IPアドレスを制限する
特定のIPアドレスからだけログインできるように設定することで、より安全度を高めます。-接続元IPアドレスを制限する
root権限で設定します。
# vi /etc/hosts.allow
sshd:192.168.xxx.xxx 192.168.xxx.xxx 半角スペースで区切る事で複数アドレスを指定可能。
7. ssh接続時のコマンドを省略するために
上記の手順により、安全に公開鍵認証でのssh接続ができるようになりました。しかし、接続時にオプションの指定やユーザー名・ホスト名・ポート番号を入力すると手間がかかります。
そこで、クライアント側の /.ssh/config ファイルにそれらの情報を記述することでssh接続のコマンドを省略することができます。
$ vi ~/.ssh/config
Host [任意の名前]
Hostname [接続先のIPアドレスまたはドメイン名]
User [接続先のユーザー名]
IdentityFile ~/.ssh/[生成した秘密鍵ファイル]
Port [/etc/ssh/sshd_configファイルに記述してあるポート番号]
/.ssh/config ファイルを保存したらターミナルを再起動してください。これ以降は、
ssh -i ~/.ssh/[秘密鍵ファイル名] [接続先のユーザー名]@[接続先のIPアドレス] -p [任意のPort番号]
上記のように入力していたものが、以下のように省略されたコマンドで接続できるようになります。
ssh [任意の名前]
8. トラブルシューティング事例
『Permission denied』とエラーが出る。
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
上記のエラーが出た場合は、接続先サーバの .ssh ディレクトリのパーミッション(700)や、 authorized_keys ファイルのパーミッション(600)、各ディレクトリや鍵ファイルの所有者が適切でない可能性があります。
接続先サーバにroot権限でログインし、tail /var/log/secure でログを確認し、エラーの原因を確かめてみましょう。
root権限でログを確認します。
# tail /var/log/secure ※ubuntuの場合は/var/log/auth.log
以下の表記を見つけました。
Jan 6 22:22:24 centos7 sshd[1885]: Authentication refused: bad ownership or modes for file /home/[接続先サーバのユーザー名]/.ssh/authorized_keys
authorized_keys のパーミッションが適切でないようです。現在設定されているパーミッションを確認してみます。
.ssh $ ls -l
-rw-rw-rw- 1 linucuser linucuser 124 Jan 2 22:22 authorized_keys
authorized_keys に現在設定されているパーミッションは 666 でした。正しいパーミッション 600 へ修正することで、公開鍵認証によるssh接続は成功します。
.ssh $ chmod 600 authorized_keys
.ssh $ ls -l
-rw------- 1 linucuser linucuser 124 Jan 2 22:22 authorized_keys
以下に、公開鍵認証におけるディレクトリ・ファイルの推奨パーミッションを整理しておきます。
クライアント | サーバ | |
---|---|---|
/home | 700 | 700 |
/home/user | 700 | 700 |
/home/user/.ssh | 700 | 700 |
秘密鍵 | 600 | - |
authorized_keys | - | 600 |
ファイルやディレクトリの所有者も確認しましょう
クライアント側のディレクトリ・ファイルの所有者/所有グループはログインさせたいユーザー、サーバ側はログインを実行するユーザーのものになっている必要があり、所有者がrootで公開鍵認証によるssh接続を試みるとエラー(Permission denied)が出ます。
パーミッションを適切なものに変更してもエラー(Permission denied)が出る場合は、上記の表で挙げたディレクトリやファイルの所有者/所有グループを確認し、chownコマンドで所有者/所有グループを変更しましょう。
$ ls -al
drwx------ 1 root root 124 Jan 2 22:22 .ssh .sshディレクトリの所有者/所有グループがroot
# chown root:root /home/[接続先サーバのユーザー名]/.ssh root権限で.sshディレクトリの所有者/所有グループを変更
サーバ側で公開鍵認証が許可されていないパターン
上記の通り設定を見直してログインを試みても『Permission denied』が表示される場合があります。
クライアント側でsshコマンドに -v オプションを加えてデバッグモードを起動し、ログイン出来ない原因を探ってみましょう。
$ ssh -v @192.168.xxx.xxx
以下のログを発見しました。
debug1: Authentications that can continue: gssapi-keyex,gssapi-with-mic
この行は接続先サーバで認証可能な方式が記述されていますが、公開鍵認証方式 publickey が記述されていません。つまり、このサーバは公開鍵認証によるログインを許可していません。
サーバ側のファイル /etc/ssh/sshd_config を編集し、公開鍵認証を許可する必要があります。
root権限で編集します。
# vi /etc/ssh/sshd_config
`PubkeyAuthentication no`部分を`PubkeyAuthentication yes`に変更
:wqで保存終了
上記の内容で編集後、sshdを再起動して変更を反映させましょう。
# service sshd restart
Redirecting to /bin/systemctl restart sshd.service
『Connection refused』とエラーが出る。
ssh: connect to host 192.168.xxx.xxx port 22: Connection refused
上記のエラーが出た場合は、クライアント側が指定したポート番号とサーバ側とのポート番号が合っていないため、ssh接続が拒否されたケースが考えられます。
sshコマンドで -p オプションにより接続先ポート番号を指定しない場合、デフォルトではポート番号22にssh接続されます。正しく接続するためには、接続したいサーバ側の /etc/ssh/sshd_config ファイルで指定されているポート番号を指定する必要があります。
このエラーが出た場合、サーバ側の /etc/ssh/sshd_config に記述されてあるポート番号を確認しましょう。
root権限で確認します。
# vi /etc/ssh/sshd_config
以下の記述を発見しました。
Port 11122
このサーバではポート番号 11122 を使用しているので、クライアント側からssh接続を試みる際は、以下のように -p オプションにて接続先ポートを指定する必要があります。
$ ssh -p 11122 -i ~/.ssh/[秘密鍵ファイル名][接続先サーバのユーザー名]@[接続先サーバのIPアドレス]
【参考】