サーバーセキュリティ基礎: ドアを開ける前に、まず鍵を確認しよう

「自分のサーバー」になった瞬間、すべてが自分の責任になる

前回、私はLinuxのCLIとパーミッション(Permission)という壁を越えた。chmod、chown、そして絶対にやってはいけないchmod 777まで。ファイル単位のアクセス制御はある程度つかめた。

しかし、その時の私は大きな勘違いをしていた。「ファイルパーミッション」さえきちんと管理すればサーバーは安全だと思っていたのだ。

「サーバーセキュリティ? それってセキュリティチームの仕事じゃないんですか?」

大企業ならそうかもしれない。しかし私は一人開発者だ。サーバー管理者も、セキュリティ担当者も、ネットワークエンジニアも、すべて「自分」だった。セキュリティのすべての責任が自分の肩にのしかかっていた。

そしてそれを思い知らされたのは、ある月曜日の朝に見つけたサーバーのアクセスログだった。

ファイルパーミッション(chmod)は、部屋の中にある引き出しの鍵にすぎない。建物そのものの玄関ドアは、別で管理する必要がある。

危機: 誰かが私のサーバーのドアを叩いていた

月曜の朝、習慣のようにサーバーにSSHで接続してログを確認していたところ、おかしなものを見つけた。

# 最近のSSHログイン失敗履歴を確認
$ grep "Failed password" /var/log/auth.log | tail -20

画面に表示されたログを見て鳥肌が立った。

Feb 10 03:14:22 sshd: Failed password for root from 185.220.xx.xx
Feb 10 03:14:25 sshd: Failed password for root from 185.220.xx.xx
Feb 10 03:14:27 sshd: Failed password for admin from 185.220.xx.xx
Feb 10 03:14:30 sshd: Failed password for ubuntu from 185.220.xx.xx
...

深夜3時から数百件のログイン試行。IPは海外。アカウント名はroot、admin、ubuntuと順番に試していた。これは誰かが「自動化プログラム(ボット)」を動かしてパスワードをブルートフォース(総当たり)していたのだ。

「えっ? 自分、まだハッキングされてないよね…?」

幸い突破はされていなかった。しかし、ドアの前で鍵を一つずつ試している泥棒を目の前にして「入られてないから大丈夫」と言えるだろうか? 私はすぐにサーバーのセキュリティ状態の点検を始めた。

パブリックIPを持つサーバーは、24時間世界中から自動化攻撃を受けている。私のサーバーも例外ではない。

ステップ1: 玄関を施錠する — SSHのセキュリティ強化

サーバーの玄関ドアはSSH(Secure Shell)だ。私がサーバーに接続する時に使う、まさにそれ。問題は、ハッカーも同じドアから入ろうとすることだ。まずはこの玄関を強化する必要がある。

SSHポートの変更 (デフォルト22番 → 別の番号)

SSHのデフォルトポートは22番だ。ハッカーの自動スキャナーは真っ先に22番ポートを叩く。ポート番号を変えるだけで、ブルートフォース攻撃の90%以上をフィルタリングできる。

# SSH設定ファイルを開く
$ sudo vi /etc/ssh/sshd_config

# ポート番号を変更 (デフォルト22 → 例: 2222)
Port 2222

# SSHサービスを再起動
$ sudo systemctl restart sshd

例えるなら、泥棒は普通1階の正面玄関(22番)を狙う。入り口を3階の屋上ドア(2222番)に移せば、泥棒のほとんどはドアの位置すら見つけられない。

rootアカウントによる直接ログインの遮断

ログを見ると、ハッカーが真っ先に試すアカウントが「root」だ。rootはLinuxの最高管理者アカウントなので、これを突破すればサーバー全体を掌握できるからだ。

# SSH設定ファイルでrootによる直接ログインを禁止する
$ sudo vi /etc/ssh/sshd_config

PermitRootLogin no

これでrootではSSH接続自体ができなくなる。一般アカウントでログインしたあと、必要なときだけ sudo で権限を昇格させればよい。

パスワードの代わりにSSH鍵認証

パスワードがどれだけ複雑でも、自動プログラムが数万通りの組み合わせを試せば、いつかは突破されうる。最も確実な方法は、パスワードログイン自体をオフにして、「SSH鍵(Key)」でのみ接続することだ。

# 自分のPC(ローカル)でSSH鍵ペアを生成
$ ssh-keygen -t rsa -b 4096

# 公開鍵をサーバーにコピー
$ ssh-copy-id -p 2222 user@my-server-ip

# サーバー側でパスワードログインを無効化
$ sudo vi /etc/ssh/sshd_config
PasswordAuthentication no

SSH鍵認証は「鍵」ではなく「指紋認証」だ。パスワード(鍵)は複製できるが、自分のPCにしか存在しない秘密鍵(指紋)は事実上複製不可能だ。


ステップ2: 塀を立てる — ファイアウォール(Firewall)

玄関(SSH)を強化したら、次は建物の周りに塀を立てて出入り口を制御する番だ。これが「ファイアウォール(Firewall)」である。

サーバーには合計65,535個のポート(出入り口)がある。ファイアウォールがなければ、この6万個の扉がすべて開いているのと同じだ。必要な扉だけを開け、残りはすべて閉めなければならない。

Linuxで最も手軽に使えるファイアウォールツールは「UFW(Uncomplicated Firewall)」だ。

# UFWを有効化
$ sudo ufw enable

# デフォルトポリシー: 入ってくる通信はすべて拒否、出ていく通信は許可
$ sudo ufw default deny incoming
$ sudo ufw default allow outgoing

# 必要なポートだけを開ける
$ sudo ufw allow 2222/tcp   # SSH (変更したポート)
$ sudo ufw allow 80/tcp     # HTTP
$ sudo ufw allow 443/tcp    # HTTPS

# 現在のファイアウォール状態を確認
$ sudo ufw status
ポート 用途 開放
2222 SSH (変更後ポート) ✅ 許可
80 HTTP (Web) ✅ 許可
443 HTTPS (セキュアWeb) ✅ 許可
22 SSH (デフォルト、使用しない) ❌ 遮断
その他 すべて ❌ 遮断

6万個の扉のうちたった3個だけを開けておき、残りはレンガで塞いだ。泥棒が叩く扉そのものが消えたのだ。

ファイアウォールの原則はシンプルだ。「すべて閉じて、必要なものだけ開ける。」

ステップ3: 通信の暗号化 — HTTPS

サーバーがWebサービスを提供するなら、ユーザーとサーバーの間の通信も保護しなければならない。それが「HTTPS」だ。

HTTPはデータを「はがき」のようにそのまま送るものだ。途中で誰でも中身を覗くことができる。HTTPSはデータを「封をした封筒」に入れて送るものだ。途中で奪われても中身を読むことはできない。

ユーザーがログインフォームに入力したID/パスワードがHTTPで送信されるとどうなるか? カフェのWi-Fiを共有している誰かが、その内容をそのまま見ることができてしまう。

実務でHTTPSを適用する一番簡単な方法は、「Let’s Encrypt」で無料SSL証明書を発行してもらうことだ。

# Certbotインストール (Let's Encrypt自動化ツール)
$ sudo apt install certbot python3-certbot-nginx

# 証明書の発行とNginxへの自動適用
$ sudo certbot --nginx -d mydomain.com

# 自動更新のテスト (証明書は90日ごとに更新が必要)
$ sudo certbot renew --dry-run

この数行のコマンドだけで、自分のサービスのアドレスが http:// から https:// に変わり、ブラウザのアドレスバーに鍵アイコンが表示される。ユーザーに「このサイトは安全です」という信頼を与えるわけだ。


ステップ4: 自動防御システム — Fail2Ban

SSHポートを変更し、鍵認証を設定しても、世の中にはしつこいボットが存在する。変更されたポートを見つけ出して接続を試みる連中が必ずいる。

こういう時に便利なのが「Fail2Ban」だ。一定回数以上ログインに失敗したIPを自動で遮断してくれるツールだ。

# Fail2Banインストール
$ sudo apt install fail2ban

# SSH保護の設定
$ sudo vi /etc/fail2ban/jail.local
[sshd]
enabled = true
port = 2222
maxretry = 5
bantime = 3600
findtime = 600
設定 意味
maxretry = 5 5回間違えたら
bantime = 3600 1時間、そのIPを遮断する
findtime = 600 10分以内に5回失敗した場合に適用
# Fail2Banを起動
$ sudo systemctl enable fail2ban
$ sudo systemctl start fail2ban

# 現在遮断中のIPを確認
$ sudo fail2ban-client status sshd

Fail2Banは玄関の前に立てた「防犯カメラ + 自動施錠」だ。怪しい人物がパスワードを何度も間違えると、自動で出入りを禁止してくれる。

サーバーセキュリティは一重ではなく、何重もの安全装置を積み重ねることだ。

実務アドバイス: セキュリティチェックリスト

これまで設定してきた内容をチェックリストにまとめる。サーバーを新しくセットアップするたびにこのリストをなぞれば、基本的な防御ラインは確保できる。

# 項目 コマンド/設定
1 SSHポート変更 sshd_config内の Port 2222
2 rootログインの遮断 PermitRootLogin no
3 SSH鍵認証への切り替え PasswordAuthentication no
4 ファイアウォール有効化 ufw enable、必要なポートだけ許可
5 HTTPSの適用 Let’s Encrypt + Certbot
6 Fail2Banのインストール ログイン失敗時に自動でIP遮断
7 定期アップデート sudo apt update && sudo apt upgrade

7番が意外と重要だ。セキュリティの脆弱性は毎日のように発見される。どれだけファイアウォールを立てても、OSやソフトウェアそのものに穴があれば意味がない。定期的なアップデートは、もっとも基本的でありながら、もっとも効果的なセキュリティ対策だ。


おわりに: セキュリティは特別なものではなく、習慣だ

最初は「セキュリティ」という言葉が大げさに感じられた。ハッキング防御、侵入検知、暗号化… 映画の中にしか出てこないような話だと思っていた。

しかし実際にやってみると、大層な技術が必要なわけではなかった。SSHポートを変え、ファイアウォールをオンにし、鍵認証を設定し、Fail2Banを入れる。数行のコマンドで終わる作業だった。重要なのは「知っていること」ではなく「実行すること」だった。

セキュリティ事故は、高度なハッキング技術ではなく、基本的な対策を取らなかったサーバーで起きる。

あの日以来、私はサーバーを新しくセットアップするたびに、コードを上げる前に必ずこのセキュリティチェックリストから実行している。ドアを開ける前にまず鍵を確認すること。それがサーバーを守るもっとも基本的な姿勢だ。

ここまで私たちは、Linuxという野生で生き残るための基礎体力(CLI、パーミッション、セキュリティ)を鍛えてきた。しかし、依然として根本的な問題が残っている。自分のノートパソコン(Windows)とLinuxサーバーの環境が違う、ということだ。Javaのバージョンも違えば、ライブラリも違う。

「自分のPCでは動くんですけど?」という言い訳を永遠に終わらせる技術がある。次回は、環境の違いをまるごと無くしてしまう「仮想化とコンテナ」について見ていこう。

コメントする