公開鍵認証編~サーバーへの接続を制限しよう~ - Linuxセキュリティ入門(3)
こんにちは、川井です。
最近はオートロック式のマンションに住んでいるため芸能レポーターが押し寄せても安心ですが(笑)、小さい頃はこぢんまりとした1DKの一軒家に住んでいました。ある日遊び疲れて家へ帰ると家の中のありとあらゆるものがひっくり返っており…、おこづかい入れの箱もフタが外れて中身が消失(涙)。戸締りが悪かったかは不明とはいえ、おぼろげな記憶をたどると玄関のトビラが木製だった気がします。しっかり鍵をかけても、犯罪を誘発する要因は他にあるのかもしれません……。
便利さとセキュリティの関係
一般的にさくらのサービスを使用して各種設定作業をする場合、SSH(Secure Shell)プロトコルを使った接続でのコンソール操作が前提となっている場合がほとんどです。そこでクライアントからサーバーへの安全な設定の手立てを考えると、次の様なところでしょうか。
接続元IPアドレスでSSH接続を制限する・・・③
サーバーへ接続するIPアドレスを制限すれば悪意のあるアクセスをほとんどなくせます。とはいえ、会社だけから保守するとは限らず、出先のスキマ時間に不具合を直して〜という要求や、授業の間の休み時間に趣味のサイトをいじりたいとかあるでしょう。自宅や会社にいても固定IPの契約をしなければ、ルータの電源が切れた拍子にIPアドレスが変わる可能性もあります。IPアドレスではないSSH接続のアクセス制御を考えてみました。
SSH接続先のクライアントを制限する → SSH接続先のクライアントを公開鍵 ( 認証鍵 )で制限する・・・❸
SSH接続をするために、サーバーとして OpenSSHサーバーが使われ、クライアントとしてWindowsならTera Termなどのターミナルソフトウェア、macOSであれば標準のターミナル上でOpenSSHクライアントの利用が可能です。SSH接続するソフトウェアであれば公開鍵 ( 認証鍵 )を簡単に作れます。また、WindowsのTera TermはSSHで安全なファイル転送ができ、macOSもSSHを利用した安全なファイル転送が可能です。
SSH接続はどんなことをするのか再確認する
サーバーに接続して作業をするのであれば、ユーザ名とパスワードをサーバーへ転送・確認する必要があるでしょう。SSH以前、Telnetやrshやrloginなどのプロトコルでは平文でユーザ名とパスワードを送っていたため、ネットワークを流れる途中で覗かれてしまう可能性がありました。一方、SSH接続ではユーザー認証部分を含むすべてのネットワーク上の通信が暗号化されます。
何も設定しないで直にSSHで接続する方式をパスワード認証と呼びます。パスワード認証を利用する時もサーバー・クライアント間で共通鍵を共有し、ユーザー名とパスワードを鍵で暗号化してサーバーへ送ることで盗聴を防いでいます。ただ、繰り返して何回も自動生成したパスワードを送り付けてパスワードを破ろうとする輩も後を絶ちません。
パスワード認証よりもセキュリティを高めるためには、通信を始める前に暗号化する公開鍵をサーバーへ登録しておくだけです。この、2つ目の方式を公開鍵認証と呼び、公開鍵認証ではユーザ名とパスワードを転送・照合するユーザ認証はおこなわれず、代わりに公開鍵の指紋照合およびクライアントが公開鍵に対応する秘密鍵の持ち主であることを確認できれば、ログインを許可します。
ユーザーが秘密鍵で署名を作り、サーバーが公開鍵で検証することで、確かに秘密鍵の持ち主であることを確認できます。これから使う秘密鍵と公開鍵はセットとしてクライアントで作ります。
名前 | ビット数 | 説明 | その他 |
---|---|---|---|
RSA1:Rivest Shamir Adleman | 1024 | SSHバージョン1で使われているが、本バージョン自体が危険なため使えないことが多い | 非推奨 |
DSA:Digital Signature Algorithm | 1024 | 非推奨 | |
RSA | 2048(1024〜) | SSHバージョン2で使う、昔から広く使われている。最近は最低2048ビット、できれば3072ビット推奨。古い環境でも使えるため無難 | 推奨 |
ECDSA:Elliptic Curve Digital Signature Algorithm | 256 か 384 か 521 | 楕円曲線DSA | |
ED25519 | 256 | EdDSA ( エドワーズ曲線デジタル署名アルゴリズム ) の1実装 |
鍵には幾つかの方式があり、できるだけ長くて破られ辛い鍵を作ると良いでしょう。アルゴリズムとしてRSA、DSA、RSA1、DCDSA、ED25519が用意されています。RSAはデフォルトのビット数が2048で、SSHバージョン2対応のため、一般的に利用されているようです(SSHバージョン1は危険なため、そもそも使えないことがが多いです)。更に安全であろうECDSAやED25519もあります。鍵となるデータはバイナリのデータで、長さを指定でき、文字列変換してファイルに保存されています。
Windowsで公開鍵を作ってSSH接続する
Windows環境のターミナルソフトウェアはTera Termの他に、PoderosaやPuTTYやRLoginなどがしのぎを削っているようです。今回は扱いやすい Tera Termを使ってみましょう。WindowsユーザでTera Termをお持ちでない方はこちらのWebサイトの Download からダウンロードしてください。ZIP圧縮されたアーカイブファイルであれば展開するだけでも使えました。
Tera Termを起動すると、新しい接続のダイアログが表示された状態です。ここは Cancel ボタンをクリックして新規接続ダイアログを閉じてください。まずはRSAの秘密鍵と公開鍵を作ってみましょう。
まずは、Tera Termの Setup メニューから「SSH KeyGenerator...」(SSH鍵の作成)を選んでください。鍵作成ダイアログが表示され、鍵のタイプ(Key type)がSSH2対応のRSA、ビット数(Key Bits)がデフォルトの2048が選ばれた状態です。Generateボタンをクリックすると、鍵の生成が始まります。
この状態で鍵はまだ保存されていません。強固なセキュリティが欲しいので、パスフレーズ(Key passphrase)とパスフレーズの確認(Confirm passphrase)に同じパスフレーズを入力します。パスフレーズという言葉はパスワードよりも文章的な文字列とはいえ、いつも使われているパスワードでも構わないかと(^_^;)。鍵をファイルに保存する必要がありますので、「Save public key」ボタンと「Save private key」ボタンをそれぞれクリックしてください。
公開鍵と秘密鍵はそれぞれ別のファイルに保存することになるので、ドキュメント フォルダに新しくフォルダを作ると良いでしょう。保存する場所を選ぶダイアログで右クリックして「新規作成(X)」から「フォルダ(F)」を選ぶと「新しいフォルダー」が作られます。「新しいフォルダー」を右クリックして「名前の変更(M)」を選び、フォルダ名を適当な名前に変更します。作成したフォルダをダブルクリックしてフォルダの中に移動してから、「保存(S)」ボタンをクリックし、次に、「Save private key」ボタンをクリックしてください。最後に鍵作成ダイアログの「Close」ボタンでダイアログを閉じてから、Tera TermでSSH接続してみましょう。
Tera TermのFileメニューから「New connection… Alt+N」をクリックしてください。新規接続ダイアログが表示されますので、Hostに接続するサーバーのIPアドレスまたはドメインを含んだホスト名を指定し、OK ボタンをクリックします。
初回接続時は接続先がリストに登録されていませんので、一回だけワーニングのダイアログが出ます。これは接続先がなりすましでないかをサーバのホスト鍵によって確認するダイアログです。ここではContinue ボタンをクリックしてください。すると認証画面に遷移します。この時点ではまだ、サーバーへ公開鍵を転送していないのでパスワード認証する必要があるため、User name(ユーザ名)とPassphrase(パスワード)を入力し、OK ボタンをクリックします。
接続したら、公開鍵を保存しておく場所となる「.ssh」ディレクトリを作ったり、.sshディレクトリのモードを変更する必要があります。.sshディレクトリはホームディレクトリ(ログインした場所がホームディレクトリなので気にすることもありません)に mkdir コマンドで作り、モードは自分だけがアクセスアクセスできるように chmod コマンドで指定してください。保存場所ができたら公開鍵を登録しましょう。
.ssh/authorized_keysをテキストエディタで開き(存在しない場合は新規作成になります)、公開鍵のファイル(id_rsa.pub)の中身をコピーアンドペーストします。間違ってid_rsaファイルの中身をコピーアンドペーストしないよう注意してください。また、.ssh/authorized_keysのパーミッションは600または644である必要がありますので、「ls -la」コマンドでパーミッションを確認し、600または644でない場合は「chmod 600 .ssh/authorized_keys」とします(ここでは手順を簡略化するためにパーミッションを600に変更する手順としています)。公開鍵ファイルが登録できたら、Tera TermのFileメニューから「New connection… Alt+N」をクリックします。
SSH認証ダイアログではUser name(ユーザ名)に「root」を指定し、Passphraseに先ほど指定したパスフレーズを入力し、Authentication method(認証方法)の枠内の「Use RSA/DSA/ECDSA/EDD25519 key to log in」のラジオボタンを選択し、Private key file(秘密鍵のファイル)の一番右の「…」ボタンをクリックして秘密鍵のファイル(id_rsa)を選んでください(秘密鍵は転送されません)。OK ボタンをクリックするとサーバーへ接続されます。
macOSで公開鍵を作ってSSH接続する
macOSはOpenSSHのクライアントが最初から用意されているため、より気軽に安全なSSH接続できます。また、Windows 10からはPowerShellにOpenSSHをはじめとするUNIX(Linux)環境が用意されたため、Windows10のPowerShellでもここでの説明が使える様になりました。macOSで公開鍵と秘密鍵を作り、公開鍵認証でサーバーへ接続してみましょう。macOSでターミナルを起動してください。
$ ssh-keygen -t rsa ↩︎ Generating public/private rsa key pair. Enter file in which to save the key (/Users/kawai/.ssh/id_rsa): ←よければEnter Created directory '/Users/kawai/.ssh'. Enter passphrase (empty for no passphrase): ←パスフレーズを入力 Enter same passphrase again: ←もう一度同じパスフレーズを入力 Your identification has been saved in /Users/kawai/.ssh/id_rsa. Your public key has been saved in /Users/kawai/.ssh/id_rsa.pub. The key fingerprint is: SHA256:oYmuIK/86PjEC98cYSKxKbqHWItCenXSqOi69GXHC2U kawai@kawai-no-iMac.local The key's randomart image is: +---[RSA 2048]----+ | | | | |. . | | + . o . | |= . +ooES | |o+.++.* | |O*o+o* o | |%BB=o.o . | |@@Boo . | +----[SHA256]-----+ $ ls -al .ssh ↩︎ total 16 drwx------ 4 kawai staff 136 8 19 15:38 . drwxr-xr-x@ 128 kawai staff 4352 8 19 15:29 .. -rw------- 1 kawai staff 1766 8 19 15:38 id_rsa -rw-r--r-- 1 kawai staff 416 8 19 15:38 id_rsa.pub
はじめに、OpenSSHパッケージとして提供されている ssh-keygen コマンドを使って公開鍵を作成します。オプションとしては公開鍵と秘密鍵の暗号化方式を -t オプションで rsa方式を指定します。途中で問われる秘密鍵ファイルの保存場所に対しては↩︎(return)を、passphraseの問い合わせにはパスフレーズを入力してください。.sshディレクトリの下を lsコマンドで確認してみましょう。次に公開鍵をサーバーへ転送します。
$ ssh-copy-id root@00.000.000.00 ↩︎ The authenticity of host '00.000.000.00 (00.000.000.00)' can't be established. ECDSA key fingerprint is SHA256:ED0EqS3RENCjWIXaLVkOL91yf8rnGAiTyWjcrKfR560. Are you sure you want to continue connecting (yes/no)? yes ↩︎ Warning: Permanently added '00.000.000.00' (ECDSA) to the list of known hosts. root@00.000.000.00's password: ←パスフレーズを入力
macOSではOpenSSHが利用できますので、ssh-copy-id コマンドを使用して公開鍵を転送します。転送後、実際にSSH接続してみましょう。
$ ssh root@00.000.000.00 -v ↩︎ OpenSSH_7.4p1, LibreSSL 2.5.0 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Connecting to 00.000.000.00 [00.000.000.00] port 22. debug1: Connection established. debug1: identity file /Users/kawai/.ssh/id_rsa type 1 debug1: key_load_public: No such file or directory debug1: identity file /Users/kawai/.ssh/id_rsa-cert type -1 debug1: key_load_public: No such file or directory debug1: identity file /Users/kawai/.ssh/id_dsa type -1 debug1: key_load_public: No such file or directory debug1: identity file /Users/kawai/.ssh/id_dsa-cert type -1 debug1: key_load_public: No such file or directory debug1: identity file /Users/kawai/.ssh/id_ecdsa type -1 debug1: key_load_public: No such file or directory debug1: identity file /Users/kawai/.ssh/id_ecdsa-cert type -1 debug1: key_load_public: No such file or directory debug1: identity file /Users/kawai/.ssh/id_ed25519 type -1 debug1: key_load_public: No such file or directory debug1: identity file /Users/kawai/.ssh/id_ed25519-cert type -1 debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_7.4 debug1: Remote protocol version 2.0, remote software version OpenSSH_7.4 debug1: match: OpenSSH_7.4 pat OpenSSH* compat 0x04000000 debug1: Authenticating to 00.000.000.00:22 as 'root' debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: algorithm: curve25519-sha256 debug1: kex: host key algorithm: ecdsa-sha2-nistp256 debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC:compression: none debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: compression: none debug1: expecting SSH2_MSG_KEX_ECDH_REPLY debug1: Server host key: ecdsa-sha2-nistp256 SHA256:ED0EqS3RENCjWIXaLVkOL91yf8rnGAiTyWjcrKfR560 debug1: Host '00.000.000.00' is known and matches the ECDSA host key. debug1: Found key in /Users/kawai/.ssh/known_hosts:1 debug1: rekey after 134217728 blocks debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: rekey after 134217728 blocks debug1: SSH2_MSG_EXT_INFO received debug1: kex_input_ext_info: server-sig-algs= debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: publickey,password debug1: Next authentication method: publickey debug1: Offering RSA public key: /Users/kawai/.ssh/id_rsa debug1: Server accepts key: pkalg rsa-sha2-512 blen 279 Enter passphrase for key '/Users/kawai/.ssh/id_rsa':
←パスフレーズを入力 debug1: Authentication succeeded (publickey). Authenticated to 00.000.000.00 ([00.000.000.00]:22). debug1: channel 0: new [client-session] debug1: Requesting no-more-sessions@openssh.com debug1: Entering interactive session. debug1: pledge: network debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0Last failed login: Mon Aug 19 16:06:35 JST 2019 from 000.00.0.000 on ssh:notty There were 1057 failed login attempts since the last successful login. Last login: Mon Aug 19 15:22:11 2019 from xxxxxxxx000000000000.xxxxxx.net SAKURA Internet [Virtual Private Server SERVICE] [root@www0000000 ~]#
sshコマンドには接続先の「ユーザ名@IPアドレス」を指定し、接続の様子がわかるように -v オプションも付けました。鍵の作成時に指定したパスフレーズの入力が求められ、正しければログインが完了します。通常時は -v オプションを付けないので背景が黄色となっている行のみが表示されます。
SSH接続のセキュリティをより高める
OpenSSHサーバーの設定としてはもう2つお勧めがあります。WindowsとmacOSの2つの例では思いっきりrootユーザーで接続するなんて危なっかしいことをしてしまいましたので…、由緒正しき?作法も書いておきましょう。通常は一般ユーザで接続し、必要に応じて suコマンドでrootユーザーになってからコマンドを実行するか、sudoコマンドを使ってroot特権でコマンドを実行する手法が常識です。
そしてまず1つ目の設定は、前述の常識に合わせて「SSH接続でrootユーザがログインできなくする」という設定です。ただ、気をつけないといけないのは設定を間違えるとログインできなくなってしまうため、設定の前に、1回目でも紹介したさくらのVPSまたはさくらのクラウドのコンソールを開いてログインをしておくことを強くお勧めします。こうすることでログインできなくなってもリカバリーすることができます。そして、OpenSSHのサーバの設定ファイルである /etc/ssh/sshd_config ファイルを書き換えます。
# ls -l /etc/ssh/sshd_* ↩︎ -rw------- 1 root root 3907 Jul 23 19:03 /etc/ssh/sshd_config -rw-------. 1 root root 3908 Apr 23 13:28 /etc/ssh/sshd_config.orig ←この行があれば次のコピーはしない # cp -p /etc/ssh/sshd_config /etc/ssh/sshd_config.orig ↩︎ # sed -i 's/^#PermitRootLogin yes$/PermitRootLogin no/g' /etc/ssh/sshd_config ↩︎
設定ファイルを書き換える前に ls コマンドでファイルのバックアップがあるかを確認し、バックアップファイルがなければ cp コマンドで設定ファイルのバックアップファイルを作成。もしも、バックアップファイルがある場合はコピーしないでください。OpenSSHサーバーの /etc/ssh/sshd_config 設定ファイルの「#PermitRootLogin yes」という行を「PermitRootLogin no」へ sed コマンドで変更しましょう(OpenSSH-server-7.4-p1-16であれば38行目となります。viエディタが使える方はviエディタで変更しても大丈夫です)。
もう一つのおすすめはパスワード認証の禁止で、すなわち、公開鍵認証でのログインだけを可能とする設定です。こちらも1つ目の設定同様に操作を間違えてログインできなくなってしまうこともありますので、是非ともコンソールを開いておきましょう。
# sed -i 's/^PasswordAuthentication yes$/PasswordAuthentication no/' /etc/ssh/sshd_config ↩︎ # systemctl restart sshd ↩︎
パスワード認証の禁止は、OpenSSHサーバーの /etc/ssh/sshd_config 設定ファイルの「PasswordAuthentication yes」という行を「PasswordAuthentication no」へ sed コマンドで変更します(OpenSSH-server-7.4-p1-16であれば65行目)。OpenSSHサーバーの設定を変えたら、1回目でも紹介した systemctl コマンドでOpenSSHサーバーを再起動してください。再起動してメッセージが何も表示されなければ問題ないです。macOSなどのクライアントから ssh コマンドで再接続してみましょう。
$ ssh kawai@00.000.000.00 -o PreferredAuthentications=password -o PubkeyAuthentication=no ↩︎ Permission denied (publickey). $ ssh kawai@00.000.000.00 ↩︎ Enter passphrase for key '/Users/kawai/.ssh/id_rsa': ←パスフレーズを入力 Last failed login: Mon Aug 19 19:42:16 JST 2019 from xxxxxxxx000000000000.xxxxx.net on ssh:notty There was 1 failed login attempt since the last successful login. Last login: Mon Aug 19 19:41:47 2019 from xxxxxxxx000000000000.xxxxx.net SAKURA Internet [Virtual Private Server SERVICE] [kawai@www00000xx ~]$
1回目の ssh コマンドではユーザー名がkawaiで -o オプションでパスワード認証を優先と公開鍵認証を不可とし、アクセス拒否(Permission denied)エラーが出れば設定した通りなので正常です。2回目の ssh コマンドではオプションを指定しませんので、公開鍵認証を試して秘密鍵のパスフレーズの問い合わせに答え、パスフレーズが合っていたのでログインができました。
以上の様に、公開鍵認証を使うとセキュリティはかなり高くなります。