Claude × Debian サーバー編 05

第5章 守りの基本

攻撃面を減らし、更新を自動化する

なぜ守りの章が、サービスを動かす章より先か

普通の入門書なら、ここでそろそろ「何かを動かしてみよう」という章が来る頃だ。Webサーバーを立てる、ファイル共有を始める、自分のアプリを公開する——楽しいのはそこからだ。

この本は、その前に守りの章を置く。理由は単純で、サーバーを世界に公開した瞬間、世界中のbotが一斉に扉を叩き始めるからだ。これは脅し文句ではない。試しに、まだ何も公開していない今のうちに、SSHへのログイン失敗を覗いてみてほしい。

sudo journalctl -u ssh --since "1 hour ago" | grep -i failed
                

家庭内LANにだけ置いたサーバーなら、ここはほぼ静かなはずだ。失敗ログはせいぜい、自分が打ち間違えた数行だろう。この「静けさ」を一度自分の目で見ておくことに意味がある。公開後に同じコマンドを打つと、見知らぬIPからの失敗ログが分単位で積み上がる。その対比こそが、この章で何を守っているのかを体で理解させてくれる。

# 古いシステムでは /var/log/auth.log にも同じ記録が残る
                sudo tail -n 50 /var/log/auth.log 2>/dev/null
                

守りの濃さは、自分のサーバーがどこに置かれているかで変わる。整理すると二段階だ。

  • LAN内のみ:自宅や事務所のルーターの内側にいて、外からは直接届かない。脅威は限定的で、守りは「家庭内の事故」を防ぐ程度でいい
  • 公開(インターネットから直接届く):VPS、固定IP、ポート開放——この瞬間に脅威モデルは一段上がる。この章のすべてが必須になる

今がLAN内なら、まだ静かなうちに守りを身につけておく。 公開してから慌てて学ぶのは、扉を開け放したまま鍵の付け方を調べるようなものだ。

第一節 攻撃面という考え方

セキュリティの話は専門用語が多くて身構えるが、土台にある発想は驚くほど単純だ。

入れていないソフトは、攻撃されない。動いていないサービスは、穴にならない。 これを「攻撃面(attack surface)を減らす」という。守りの第一歩は、難しい設定を足すことではなく、要らないものを引くことだ。「引き算の設計」で繰り返した姿勢が、ここでも効く。

まず、いま自分のサーバーが外に向けて「開いている耳」を全部見る。

# いま待ち受けている(LISTEN している)ポートとプロセス
                ss -tlnp
                

出力はこんな形になる。

State   Recv-Q  Send-Q  Local Address:Port   Peer Address:Port  Process
                LISTEN  0       128     0.0.0.0:22           0.0.0.0:*          users:(("sshd",pid=701,fd=3))
                LISTEN  0       4096    127.0.0.1:631        0.0.0.0:*          users:(("cupsd",pid=812,fd=7))
                

ここで大事なのは、各行が何を意味するかを一行残らず読むことだ。0.0.0.0:22 は「すべてのネットワークインタフェースの22番ポートで待っている」——つまり外から届く。127.0.0.1:631 は「ローカルホストだけで待っている」——外からは届かない。この違いが分かると、どのサービスが本当に外に晒されているかが見える。

Claudeに聞いてみよう①:ss -tlnp の出力を読み解く

私のDebian 13サーバーで ss -tlnp を実行したら、次の出力でした:

〔ss -tlnp の出力をそのまま貼る〕
                

各行が何のサービスで、外(インターネット)から届く状態か、ローカルだけかを一行ずつ説明してください。 そのうえで、サーバー用途〔例:LAN内のファイル共有のみ〕を踏まえて、「閉じてよいもの」「閉じてはいけないもの」を理由付きで分類してください。

ss の出力を一行ずつ解説させる——これは本章で最も価値のある使い方だ。自分の目には記号の羅列でも、Claudeに渡せば「この耳は要る、この耳は塞いでいい」という地図に変わる。

要らないと判明したサービスは、止めて、自動起動も切る。

# 例:印刷サーバー cups がサーバー機では不要だった場合
                sudo systemctl disable --now cups
                # もう待ち受けていないことを確認
                ss -tlnp
                

disable --now は「いま止める(stop)」と「次回以降も起動しない(disable)」を一度にやる。攻撃面が一つ減った。

第二節 ファイアウォール——最小の許可から始める

攻撃面を引いたら、次は「残った耳のうち、誰に応答するか」を決める。これがファイアウォールの仕事だ。Debianでは ufw(Uncomplicated Firewall)が扱いやすい。

考え方は一つ。デフォルトはすべて拒否。必要なものだけを名指しで許可する。 ホワイトリスト方式だ。

sudo apt install ufw
                

ここで順番を絶対に間違えないこと。先に「全部拒否」を有効化してから SSH を許可すると、SSH で繋いでいる自分自身が締め出される。必ず allow ssh を先に書いてから enable する。

# 1. まず方針:入ってくる通信はデフォルト拒否、出ていく通信は許可
                sudo ufw default deny incoming
                sudo ufw default allow outgoing

                # 2. 自分が締め出されないよう、SSHを先に許可する(最重要)
                sudo ufw allow ssh

                # 3. ここでようやく有効化
                sudo ufw enable

                # 4. いまのルールを確認
                sudo ufw status verbose
                

enable の直前に一拍置いて、allow ssh が入っているか必ず見返す癖をつける。リモートのサーバーでこれを間違えると、物理コンソールか復旧手段がない限り入れなくなる。

LAN内だけで使うサービスなら、「特定のネットワークからだけ許可する」と書ける。これが攻撃面をさらに絞る。

# 例:自宅LAN(192.168.1.0/24)からのみ、Webアクセスを許可
                sudo ufw allow from 192.168.1.0/24 to any port 80
                # 自宅LANからだけSSHを許可したい場合(公開しないサーバー向け)
                sudo ufw allow from 192.168.1.0/24 to any port 22
                

from 192.168.1.0/24 は「このサブネット内の機器からだけ」という意味だ。外からはそもそも届かない設定になる。

Claudeに聞いてみよう②:自分の利用形態からufwルール一式を設計させる

私のDebian 13サーバーで ufw を設定します。利用形態は次の通りです:

  • 設置場所:〔例:自宅LANの内側 / VPSでインターネットに公開〕
  • 動かす予定のサービス:〔例:SSH、ファイル共有(Samba)、後でWebサーバー〕
  • 管理する端末のIP帯:〔例:自宅LANは 192.168.1.0/24〕

締め出し事故を避ける順番を守った上で、ufw のコマンドを上から順に実行できる形で出してください。 各コマンドが何を許可・拒否しているか、一行コメントを添えてください。

利用形態を正確に伝えれば、ルール一式がそのまま手元に降りてくる。自分はそれを一行ずつ吟味して実行する。 ファイアウォールは一文字の間違いが締め出しに直結するので、丸呑みせずレビューする姿勢が要る。

第三節 更新の自動化

守りで最も効くのに最も忘れられがちなのが、更新を当て続けることだ。攻撃の多くは、とっくに修正パッチの出ている既知の穴を狙う。穴は塞がれているのに、更新していないから開いたまま——これが最頻の事故だ。

サーバーは画面の前に座っていないことが多い。だから手動更新に頼らず、セキュリティ更新だけは自動で当たるようにする。Debianには unattended-upgrades がある。

sudo apt install unattended-upgrades
                

既定でセキュリティ更新を自動適用する設定になっているが、対話式に確認・有効化しておく。

sudo dpkg-reconfigure -plow unattended-upgrades
                

「自動更新を有効にしますか」に Yes と答えれば、以後はセキュリティ更新が静かに当たり続ける。何が当たったかは後から cat /var/log/unattended-upgrades/unattended-upgrades.log で読める。

ただし、更新には「再起動しないと効かないもの」がある。カーネルやglibcの更新がそれだ。再起動が必要かどうかは、ファイルの有無で分かる。

# このファイルが存在すれば、再起動が保留されている
                ls -l /var/run/reboot-required 2>/dev/null && cat /var/run/reboot-required

                # どのサービスが古いライブラリを掴んだままか教えてくれる
                sudo apt install needrestart
                sudo needrestart
                

needrestart は、再起動なしで済むものはサービス再起動だけで済ませ、本当に再起動が要るものだけを教えてくれる。サーバーをむやみに再起動したくないとき、この見分けは効く。

Claudeに聞いてみよう③:auth.log の不審な行を読み解く

私のDebian 13サーバーで、sudo journalctl -u ssh --since "today" の出力に次のような行がありました:

〔失敗ログ・見慣れない行をそのまま貼る〕
                

これは通常のbotによる総当たりですか、それとも特定の標的型の兆候ですか。 一行ずつ、何を意味しているか(接続元、試したユーザー名、失敗理由)を説明してください。 いま私が取るべき対応があれば、危険度の高い順に教えてください。

本編第8章のトラブルシュートで身につけた「ログをそのままClaudeに渡す」作法が、ここでセキュリティの文脈に移る。読めない行を恐れず貼る。 Claudeはそれを「ただのbotの雑音」か「気にすべき兆候」かに腑分けしてくれる。

第四節 fail2ban という番犬

最後に番犬を置く。fail2ban は、ログを監視して同じIPからのログイン失敗が短時間に続いたら、そのIPを一定時間ブロックする道具だ。総当たり攻撃を物理的に遅くする。

ここで優先順位をはっきりさせておきたい。fail2ban は補助であって、主役ではない。 SSHの守りの本丸は、第4章でやった鍵認証+パスワード認証の無効化だ。パスワードを無効にしてしまえば、何万回総当たりされても通らない。fail2banはその上で、ログを汚し続けるbotを追い払い、ログを読みやすく保つために置く。順番は「鍵認証が先、fail2banは後」だ。

sudo apt install fail2ban
                

Debianの作法では、設定は jail.conf を直接いじらず、jail.local に上書き分だけ書く。SSH向けの最小設定はこれだけだ。

# /etc/fail2ban/jail.local を作る(中身は下記)
                sudo tee /etc/fail2ban/jail.local > /dev/null <<'EOF'
                [DEFAULT]
                # BAN する時間(10分)
                bantime = 10m
                # この時間内に
                findtime = 10m
                # この回数失敗したら
                maxretry = 5

                [sshd]
                enabled = true
                EOF

                sudo systemctl restart fail2ban
                

動いているか、誰かをBANしたかは、専用クライアントで確認する。

sudo fail2ban-client status sshd
                

Banned IP list: に並んだIPが、いま締め出されている相手だ。LAN内だけのサーバーでは何日も空のままだろう。公開サーバーでは、数時間で数件並び始める。番犬がちゃんと吠えている証拠だ。

Claudeに聞いてみよう④:自分のサーバーに守りが揃ったか点検させる

私のDebian 13サーバーの守りの現状です:

$ ss -tlnp
                〔出力〕
                $ sudo ufw status verbose
                〔出力〕
                $ sudo fail2ban-client status sshd
                〔出力〕
                

SSHは鍵認証〔有効/まだ〕、パスワード認証は〔無効/まだ〕です。 設置は〔LAN内のみ / 公開予定〕です。 この状態で、守りとして抜けている点・順番がおかしい点・過剰な点を指摘してください。 いま公開しても致命的な穴がないか、点検してください。

複数のコマンド出力をまとめて渡すと、Claudeは「攻撃面・ファイアウォール・番犬・SSH本体」を一枚の絵として点検できる。公開ボタンを押す前の最終チェックを、Claudeに頼む。 自分一人だと見落とす「順番の穴」を拾ってくれる。

まとめ

この章でやったこと:

  1. 公開前のSSH失敗ログを覗き、「静けさ」を基準として記録した
  2. ss -tlnp で開いている耳を全部読み、要らないサービスを disable --now した
  3. ufwで「デフォルト拒否+SSHのみ許可」から始め、LAN限定の許可も覚えた
  4. unattended-upgradesでセキュリティ更新を自動化し、再起動要否の見分け方を押さえた
  5. fail2banを番犬として置き、鍵認証との優先順位を整理した

手元に残ったもの:

  • 攻撃面を絞った、ufwで守られたサーバー
  • セキュリティ更新が自動で当たり続ける状態
  • ログを読み、Claudeに渡して点検する作法(本編第8章からの継承)
  • 「公開してよいか」をClaudeに点検させるチェックリスト的な対話

守りの土台ができた。次の第6章「サービスという単位」では、いよいよ何かを動かす。サーバーの中身は結局「systemdが面倒を見るプロセスの集まり」だ。起動・停止・自動起動・ログ・障害対応を、すべて同じ型——「サービス」という単位——で扱えるようにする。この章で systemctl disable --now を打ったその動詞が、次の章の入口になる。


シリーズ全体はClaudeと一緒に学ぶDebian サーバー編 一覧から辿れる。本編(デスクトップ編)は全章一覧へ。コメント・議論は Facebook グループへ:AISeed — 生物多様性・食料・AIと暮らし

← 前: 第4章 SSHという玄関 次: 第6章 サービスという単位 →

公開する前に、守りを終わらせる。

サービスを動かすのは楽しい。だが公開した瞬間、世界中のbotが扉を叩き始める。攻撃面を減らし、更新を自動化し、番犬を置く——この章で、安心して何かを動かすための土台を作る。

AISeed — 生物多様性・食料・AIと暮らし(Facebook)