サーバーを借りました。管理画面に「IPアドレス」と「rootパスワード」が表示されています。
それで、次に何をすればいいのか分かりませんでした。
検索すると「初期設定」の記事がたくさん出てきます。私が読んだいくつかは項目が多く、どれが必須でどれが好みなのかを、自分では判断できませんでした。全部やるべきなのか、後回しでいいのか分かりませんでした。
この記事は、私が実際にやった4つをその順番で書いたものです。やらなくていいと判断したことも書きます。
そして、私は途中で自分をサーバーから閉め出しました。その話も含めます。初めてVPSを触る人がいちばん怖いのは、たぶん「壊したら戻れないのでは」だからです。
やることは4つだけです
先に全体を出します。
0. 逃げ道を先に作る ← いちばん大事
1. 自分用のユーザーを作る
2. 鍵でログインできるようにする
3. root でログインできないようにする
4. ファイアウォールを確認する
番号が0から始まっているのは、0を飛ばすと詰むからです。私は0の一部を先にやっていたので助かりました。
「セキュリティなのに、これだけ?」と思われるかもしれません。ここに入れていないもので大きいのが OSの更新です。入れていないのは軽視したからではなく、Ubuntu Server では既定で動いているからです。手を動かす必要がないかわりに、効いているかの確認はしてください。その方法は記事の最後に書きます。
0. 逃げ道を先に作る
これから、ログインの方法そのものを変えます。失敗すると入れなくなります。
入れなくなったサーバーは、外からはどうにもなりません。中に入れないと直せないのに、直さないと入れないという状態になります。
なので、作業を始める前に2つ用意します。
VNCコンソールの場所を確認しておく
契約したVPSの管理画面に、ブラウザからサーバーの画面に直接つなぐ機能があることがあります。私が使っている ConoHa VPS では「コンソール」という名前でした。
あるかどうか、名前が何かは、契約先によって違います。管理画面を見て探してください。
これは SSH とは別の経路です。SSHが完全に壊れても、こちらからは入れます。
ターミナルをもう1つ開いたまま作業する
これがいちばん効きます。
ターミナルA … 作業する。設定を変える
ターミナルB … 何もしない。開いたまま放置する
SSHの設定を変えても、すでにつながっている接続は切れません。 つまり、Aで設定を壊しても、Bはまだ生きています。Bから元に戻せます。
新しい設定が正しいかどうかは、Bで作業を続けるのではなく、3つ目の接続を新しく開いて確かめます。既存の接続で試しても、それは古い設定のまま生きているだけなので、確認になりません。
私はこの記事の全部の確認を、そのつど新しく開いた接続でやりました。
1. 自分用のユーザーを作る
root のまま使い続けません。普段の作業用に、別のユーザーを作ります。
理由は「安全のため」と説明されることが多いのですが、実感としてはもう少し具体的です。rootは打ち間違いが全部通ります。消すつもりのないものを消すコマンドも、確認なしで実行されます。
adduser --disabled-password yourname
--disabled-password は「パスワードを設定しないで作る」という指定です。外から総当たりで破られるパスワードが、そもそも存在しない状態になります。
(このあと、sudo を使うためにパスワードを設定する選択肢が出てきます。それでも外からは使えないままです。理由はそこで説明します。)
作ったユーザーに、2つの権限を足します。
usermod -aG sudo yourname
Docker を使う予定があるなら、docker グループにも入れます。
usermod -aG docker yourname
⚠️ ここは飛ばせません。sudo が使えないユーザーになります
さっき --disabled-password で作ったので、このユーザーにはパスワードがありません。
そして sudo は、既定ではそのユーザー自身のパスワードを尋ねます。
つまりこのままだと、sudo グループに入れたのに sudo が使えません。
さらに次の3番で root のログインを止めるので、管理者権限を使う手段が無くなります。
A. パスワードを設定する(迷ったらこちら)
passwd yourname
「さっきパスワードなしで作ったのに、逆では」と思うかもしれません。 そうではありません。このパスワードは、SSHでは使えないままです。
3番で PasswordAuthentication no を入れるので、外からパスワードで入る道は閉じたままです。
このパスワードが使えるのは sudo のときと、VNCコンソールから入ったときだけになります。
つまりAを選ぶと、逃げ道がもう1本増えます。 VNCコンソールに入ったあと、 そこでも管理者権限を使えるからです。
B. パスワードを尋ねられないようにする(私はこちら)
# /etc/sudoers.d/yourname という新しいファイルに1行だけ書く
yourname ALL=(ALL) NOPASSWD:ALL
私がBにしたのは、自動化のたびに入力を求められると処理が止まるからです。 自動でデプロイする予定がないなら、Bを選ぶ理由はありません。
ファイル名に「.」を入れないでください。/etc/sudoers.d/ の中は、ファイル名にドットが入っていると黙って読み飛ばされます。 yourname.conf のような名前にすると、設定を書いたのに効きません。しかも visudo -c は「書き方が正しいか」しか見ないので、ここは素通りします。yourname のように、拡張子を付けない名前にしてください。
3番の 99- の話と同じ形の落とし穴です。直前に .conf を書いたばかりなので、ここでも付けたくなりますが、逆です。
Bを選ぶ場合、このファイルは書き間違えると sudo 全体が壊れます。壊れると管理者権限が使えなくなり、直すのも管理者権限が要るので詰みます。必ず検証コマンドを通してください。
visudo -c
これが parsed OK を返すまで、次に進まないこと。私はこれを通してから進めました。
2. 鍵でログインできるようにする
パスワードの代わりに、鍵ファイルでログインします。
手元(自分のパソコン)で鍵を作ります。
ssh-keygen -t ed25519 -C "yourname@yourserver"
ed25519 は鍵の種類です。今から作るなら基本これで問題ありません。
このとき私は、契約時にもらった root 用の鍵とは別に、新しい鍵を作りました。用途ごとに分けておくと、片方をやめたいときに片方だけ止められます。
できた公開鍵(.pub のほう)を、サーバー側の作業用ユーザーに置きます。
まだパスワードでログインできる状態なら、専用のコマンドが使えます。
ssh-copy-id -i ~/.ssh/id_ed25519.pub yourname@サーバーのIPアドレス
これは置き場所も所有者も権限も、全部正しくやってくれます。 使えるなら、これがいちばん確実です。
使えない場合(パスワードログインが既に無効など)は、手で置きます。
/home/yourname/.ssh/authorized_keys
手で置いたときは、所有者と権限の両方を直します。片方だけでは足りません。
chown -R yourname:yourname /home/yourname/.ssh
chmod 700 /home/yourname/.ssh
chmod 600 /home/yourname/.ssh/authorized_keys
ここで新しい接続を開いて、作ったユーザーで入れることを確かめます。 入れなければ、次には進みません。
入れないときに、同じコマンドを何度も繰り返さないでください。失敗を繰り返すと、次の「私はここで自分を閉め出しました」の状態になります。数回試して入れなければ、いったん止めて原因を調べてください。
3. root でログインできないようにする
2番までが成功していれば、root で入る理由はもうありません。止めます。
ここがこの記事でいちばん危ない操作です。 0番の逃げ道を確保していない状態では、やらないでください。
設定ファイルが1つではない、という話
SSHの設定は /etc/ssh/sshd_config にあります。ここを開くと、たいてい上のほうにこう書いてあります。
Include /etc/ssh/sshd_config.d/*.conf
これは「このフォルダの中身も設定として読む」という意味です。そして重要なのは、この行がファイルの先頭近くにあることです。
SSHの設定は 先に書いてあるほうが勝ちます。つまり:
/etc/ssh/sshd_config.d/ の中の設定 ← 先に読まれる。こちらが勝つ
/etc/ssh/sshd_config の本文 ← あとに読まれる
私が触ったサーバーでは、本文のほうに PermitRootLogin yes(rootのログインを許す)と書かれていました。本文を書き換えても直せますが、そうしませんでした。
sshd_config.d の中に新しいファイルを作って、そこに書けば勝てるからです。
元のファイルを触っていないので、そのファイルを消せば元に戻ります。 戻し方が単純なほうが、怖くありません。
⚠️ 99- で作ると負けます(私はそれで、たまたま動いていました)
sshd_config.d の中にすでにファイルがあることがほとんどです。まず見てください。
ls /etc/ssh/sshd_config.d/
たとえば 50-cloud-init.conf というファイルがよく入っています。
そしてフォルダの中は、ファイル名の順に読まれます。
00-hardening.conf ← 先に読まれる。勝つ
50-cloud-init.conf ← あとに読まれる
さっき書いたとおり、SSHの設定は先に書いてあるほうが勝ちます。 つまり、番号が小さいファイルが勝ちます。
なので、小さい番号で作ります。
# /etc/ssh/sshd_config.d/00-hardening.conf
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
3行目を不思議に思うかもしれません。パスワードで入る道は、実は2本あります。
PasswordAuthentication を止めても、KbdInteractiveAuthentication という別の入口が残ります。
こちらのSSH本来の既定は yes で、環境によってはここからパスワードを聞かれます。
多くのUbuntuでは、本文側で既に no になっています。でも当てにしません。
この記事では、その本文に PermitRootLogin yes が書かれているのを実際に見ています。
本文は契約先が書き換えていることがある、というのがこの記事で分かったことです。
反映する前に、必ず検証する
sshd -t
これは設定ファイルの書き方が正しいかを確かめるだけのコマンドです。何も反映しません。ここでエラーが出たら、作ったファイルを消して終わりです。
正しければ、書いた2つが実際に効いているかを見ます。ここが最後の砦です。
sshd -T | grep -E "permitrootlogin|passwordauthentication|kbdinteractive"
permitrootlogin no
passwordauthentication no
kbdinteractiveauthentication no
この3行が出れば、狙いどおりです。
yes のままなら、フォルダの中で負けています。 番号の小さいファイルに書き直してください。
sshd -T は最終的にどう解釈されたかを出すので、ファイルを何枚書いたかに関係なく、
ここに出た値が本当の設定です。
restart ではなく reload
systemctl reload ssh
restart は使わないでください。 restart はSSHを一度止めて起動し直すので、つないでいる接続が切れる可能性があります。reload は設定だけ読み直すので、今つながっている接続はそのままです。設定を間違えたまま自分の接続が切れると、0番の逃げ道しか残りません。
なお、このコマンド名は環境によって違います。サービス名が ssh ではなく sshd の環境があります(RHEL系など)。また Ubuntu 22.10 以降は、SSHが「接続が来たときだけ起動する」形(socket activation)に変わっていて、この形だと reload がエラーになったり、そもそも不要だったりします。
どちらでも、確認の仕方は同じです。コマンドが成功したかではなく、sshd -T の出力と、新しく開いた接続で判断してください。「reload できた」は、設定が効いていることの証明になりません。
反映したら、新しい接続を開いて2つ確かめます。
作業用ユーザーで入れる → 入れた
root で入ろうとすると断られる → Permission denied (publickey)
Permission denied が出たら成功です。断られることが目的なので、ここでエラーが出るのが正解です。
4. ファイアウォールを確認する
ここは手順というより、知らないとハマるという話です。
ファイアウォールは、2つあります。
① VPS事業者側の設定(管理画面にある)
② サーバーのOS側の設定(ufw など)
この2つは別のものです。 片方で通していても、もう片方で塞がっていればつながりません。
私はこれを知らずに、OS側だけ見て「開いているのになぜつながらないのか」と悩みました。実際には事業者側の管理画面で、SSH用とWeb用の許可を追加する必要がありました。
つながらないときは、両方を見てください。片方だけ見て原因を探すと、いつまでも見つかりません。
⚠️ fail2ban に自分のIPをブロックされ、SSHが無応答になった(復旧手順)
作業中、突然SSHがつながらなくなりました。エラーも出ず、ただ応答がありません。
原因は fail2ban でした。
鍵の設定を試行錯誤している間に、私は何度もログインに失敗していました。fail2ban から見れば、それは攻撃と区別がつきません。 自分の家のIPアドレスがブロックされました。
助かったのは、0番で確認しておいたVNCコンソールです。ブラウザからサーバーに入って、ブロックを解除しました。
fail2ban-client set sshd unbanip <自分のIPアドレス>
sshd の部分はブロックの種類の名前で、環境によって違うことがあります。分からなければ先に一覧を見ます。
fail2ban-client status
これが、0番をいちばん最初に置いている理由です。 逃げ道を先に作っていなければ、ここで詰んでいました。
やらなくていいと判断したこと
初期設定の記事によく出てくるけれど、私がやらなかったことです。やってはいけないという意味ではありません。「最初の1台では要らない」と判断したものです。
| 項目 | やらなかった理由 |
|---|---|
| SSHのポート番号を変える | ログに残る攻撃の記録は減りますが、パスワードでのログインを止めた時点で、パスワードの総当たりは通りません。ポートを覚える手間のほうが大きいと判断しました |
| 秘密鍵にパスフレーズを付ける | 私は付けていません。ただしこれは勧められる選択ではありません。下に補足します |
| 監視ツールの導入 | 動かすものが決まる前に監視だけ入れても、何を見ればいいか分かりません。後回しにしました |
判断の基準は「今この1台で、何を守りたいか」です。 それが決まらないうちに項目を増やすと、設定しただけで終わります。
パスフレーズについては、私の判断をそのまま真似しないでください。私は「自動化のたびに入力を求められるから」という理由で付けませんでした。その理由は、あとから間違いだと分かりました。
ssh-agent という仕組みを使うと、パスフレーズの入力は最初の1回だけで済み、そのあとは自動化とも共存できます。「自動化するなら付けられない」ではありませんでした。
パスフレーズは、秘密鍵のファイルが人の手に渡ったときの最後の砦です。これから作るなら、付けたうえで ssh-agent を使うほうがいいと考えています。私が付け直していないのは、単にまだやっていないからです。
OSの更新は、4つに入れなくていいのか
入れていません。Ubuntu Server では、契約した時点ですでに動いているからです。
unattended-upgrades という仕組みが既定でインストールされ、セキュリティ更新の自動適用が有効になっています。これはUbuntu Server の公式ドキュメントに書かれている挙動です。
ここから先だけは、私の実測に基づいていません。 ここまでの手順は自分のサーバーで実際にやった記録ですが、この節は公式ドキュメントの記述をもとに書いています。だから「あなたのサーバーでもそうなっている」とは言い切れません。確認してください。
効いているかを確認する
設定ファイルを見るのが確実です。
cat /etc/apt/apt.conf.d/20auto-upgrades
両方が "1" なら有効です。
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
自動でやってくれないこと
自動更新が有効でも、次の2つは残ります。
| 残ること | どうなるか |
|---|---|
| 再起動が要る更新 | カーネルなどの更新は、再起動するまで反映されません。 既定では自動で再起動しません |
| セキュリティ更新以外 | 既定で入るのはセキュリティ更新だけです |
再起動が必要になっているかは、このファイルの有無で分かります。
ls /var/run/reboot-required
ファイルがあれば、再起動待ちの更新があるという意味です。いつ再起動するかは自分で決めることになります。
まだやっていないこと
正直に書いておきます。
fail2ban に、自分のIPアドレスを最初から除外する設定(ignoreip)を、私はまだ入れていません。 入れておけば、上に書いた閉め出しは起きませんでした。
やっていない理由は、単にまだ手を付けていないからです。効果があると分かっていて、まだやっていない、という状態です。
まとめ
契約した直後にやることは、この4つでした。
0. 逃げ道を先に作る VNCコンソールの確認 + ターミナルをもう1つ開く
1. 自分用のユーザーを作る root のまま使わない
2. 鍵でログインできるように パスワードを使わない
3. root のログインを止める 設定は sshd_config.d に追加。reload で反映
4. ファイアウォールを確認 事業者側とOS側の2つある
難しいのは手順ではなく、失敗したときに戻れる状態を先に作っておくことでした。
私が閉め出されたときに助かったのは、技術ではなく、先に逃げ道を確認していたことだけです。
次にやること
まだVPSを契約していない状態でこれを読んでいるなら、ここまでが「契約したあとにやること」の全体です。できそうだと思えたなら、次はプラン選びです。
→ VPSは2GBで足りるか — 稼働46日目の平常時を実測
私の2GB VPSで uptime が46日だった時点の平常時を測っています。後日のビルドも1回通りましたが、スワップは増えました。限界に届く条件までは測っていません。
もう契約して、この4つを終えたなら、次はアプリを載せる作業です。私はDocker Composeで動かしていて、そこで2つ踏んでいます。
