ホストセキュリティ - 不要サービス停止/TCP Wrapper【LPIC-1 110.2】

ホストセキュリティ - 不要サービス停止/TCP Wrapper【LPIC-1 110.2】

この記事で達成できること

  • ss -tulnp でリッスン中のサービスを洗い出せる
  • systemctl stop / disable / mask の違いを正確に説明できる
  • TCP Wrappers の /etc/hosts.allow/etc/hosts.deny 評価順を理解する
  • スーパーサーバ(inetd / xinetd)の役割を把握する
  • /etc/nologin・シャドウパスワード(pwconv)など周辺の防御策を扱える

LPIC-1 主題 110.2「ホストのセキュリティを設定する」の中核。攻撃面(アタックサーフェス)を減らす「不要サービスの停止」と、接続元を絞る「アクセス制御」の二本柱を押さえる。

ホストセキュリティの基本方針とは

原則は「動いていないサービスは攻撃されない」。まず不要サービスを止め、残すサービスは接続元を絞る。この優先順位を間違えない。

ホストの堅牢化は次の順序で進めると漏れがない。

  1. 何がリッスンしているかを把握する(ss -tulnp
  2. 不要なサービスを停止・無効化する(systemctl
  3. 残すサービスへの接続元を制限する(TCP Wrappers / ファイアウォール)
  4. ログインや認証まわりを締める(/etc/nologin・シャドウパスワード)

TCP Wrappers(libwrap)は新しいディストリビューションでは採用が縮小しており、Debian / Ubuntu は libwrap サポートを廃止する方向にある。ただし LPIC-1 110.2 の出題範囲には含まれるため、本記事でも仕組みを解説する。

リッスンしているサービスを確認するには

まず「今、何が外部接続を待ち受けているか」を可視化する。ss -tulnp が現行の標準コマンド。

ss -tulnp
Netid State  Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp   UNCONN 0      0            0.0.0.0:68        0.0.0.0:*     users:(("dhclient",pid=712,fd=6))
tcp   LISTEN 0      128          0.0.0.0:22        0.0.0.0:*     users:(("sshd",pid=901,fd=3))
tcp   LISTEN 0      100        127.0.0.1:25        0.0.0.0:*     users:(("master",pid=980,fd=13))

ss のオプションは次の意味。-p は root 権限がないとプロセス名が表示されない。

オプション 意味
-t TCP ソケット
-u UDP ソケット
-l リッスン中(LISTEN)のみ
-n ポート番号を名前解決せず数値表示
-p ソケットを使うプロセスを表示

ssiproute2 パッケージのコマンドで、レガシーな netstat -tulnpnet-tools)の後継。出力はほぼ同じ意味で読める。

ここで 0.0.0.0:Port は全インターフェースで待ち受け(外部到達可能)、127.0.0.1:Port はループバックのみ(外部からは到達不可)を示す。上の例では SSH(22)が外部公開、SMTP(25)はローカル限定だと読み取れる。

stop・disable・mask の違いとは

結論。stop は「今止める」、disable は「次回起動しない」、mask は「二度と起動できなくする」。役割が異なり、組み合わせて使う。

不要サービスを停止・無効化する手順

systemctl stop avahi-daemon
systemctl disable avahi-daemon
Removed "/etc/systemd/system/multi-user.target.wants/avahi-daemon.service".

stop だけでは再起動後にまた立ち上がる。永続的に止めるには disable が必須。両方を 1 行で行うのが --now

systemctl disable --now avahi-daemon

disable --now は「即時停止(stop 相当)」と「自動起動無効化(disable)」を同時に実行する。実務で最も使う形。

mask で起動不能にロックする

systemctl mask avahi-daemon
systemctl start avahi-daemon
Created symlink /etc/systemd/system/avahi-daemon.service → /dev/null.
Failed to start avahi-daemon.service: Unit avahi-daemon.service is masked.

mask はユニットファイルへのシンボリックリンクを /dev/null に張り、手動 start も依存関係による起動もすべて拒否する。disable より強い。解除は unmask

コマンド 即時停止 自動起動 手動起動 用途
stop する 変わらず 可能 一時的に止める
disable しない 無効 可能 次回から自動起動させない
disable --now する 無効 可能 実務の標準形
mask しない 無効 不可 絶対に起動させたくない場合

状態確認は systemctl is-enabled svc(自動起動の有無)と systemctl is-active svc(稼働中か)で行う。

mask したサービスは依存する他サービスの起動も巻き込んで失敗させることがある。本当に不要なものだけに使い、迷ったら disable に留める。

スーパーサーバ(inetd / xinetd)とは

スーパーサーバは複数の小規模サービスを代理で待ち受け、接続が来たときだけ対象デーモンを起動する仕組み。常駐プロセスを減らせる。

歴史的には inetd、その拡張版が xinetd。設定ファイルの構造は次の通り。

ファイル / ディレクトリ 役割
/etc/inetd.conf inetd の設定(サービスごとに 1 行)
/etc/xinetd.conf xinetd のメイン設定・デフォルト値
/etc/xinetd.d/ xinetd のサービス別設定ファイルを格納するディレクトリ

xinetd でサービスを止める基本は、該当サービス定義に disable = yes を書いて xinetd をリロードすること。

cat /etc/xinetd.d/telnet
service telnet
{
    socket_type = stream
    protocol    = tcp
    wait        = no
    user        = root
    server      = /usr/sbin/in.telnetd
    disable     = yes
}

disable = yes でそのサービスを無効化する。/etc/xinetd.confdefaults ブロックには全サービス共通の設定(ログ形式・接続数上限など)を書く。

現在のディストリビューションは systemd ソケットアクティベーション(.socket ユニット)が xinetd の役割を引き継いでいる。試験では inetd / xinetd の概念と設定ファイル位置を問われる。

TCP Wrappers のアクセス制御を理解するには

TCP Wrappers は libwrap でリンクされたサービスへの接続を、ホスト単位で許可・拒否する仕組み。/etc/hosts.allow/etc/hosts.deny の 2 ファイルで制御する。

評価順序(最重要)

公式マニュアル hosts_access(5) によると、判定は次の順で行われ、最初にマッチしたルールで確定する(first match wins)。

  1. /etc/hosts.allow を上から検索。マッチすれば許可して終了。
  2. マッチしなければ /etc/hosts.deny を検索。マッチすれば拒否して終了。
  3. どちらにもマッチしなければ許可(デフォルト許可)。

つまり allow が deny より常に優先される。閉じた運用にしたいなら「deny で全拒否してから allow で穴を開ける」のが定石。

cat /etc/hosts.deny
ALL: ALL
cat /etc/hosts.allow
sshd: 192.168.1.0/24
sshd: 10.0.0.5
ALL: LOCAL

この例では、まず hosts.deny で全サービス・全ホストを拒否(ALL: ALL)。その上で hosts.allowsshd への 192.168.1.0/2410.0.0.5 だけ、および全サービスへのローカル接続を許可している。allow が先に評価されるため、許可した接続は通り、それ以外は deny で落ちる。

書式とワイルドカード

ルールは デーモンリスト : クライアントリスト の形式(daemon_list : client_list)。

要素 意味
デーモンリスト サービスのプロセス名(sshd, vsftpd など)。ALL で全部
クライアントリスト 接続元のホスト・IP・ネットワーク。ALL で全部
ALL 常にマッチするワイルドカード
EXCEPT 「A EXCEPT B」= A にマッチするが B は除外
LOCAL ドットを含まないホスト名(ローカルホスト)

EXCEPT の例は次の通り。

cat /etc/hosts.allow
sshd: ALL EXCEPT 192.168.1.100

これは「192.168.1.100 を除く全ホストから sshd への接続を許可」を意味する。クライアントは .example.com(ドメイン後方一致)、192.168.1.(ネットワーク前方一致)といった指定も可能。

TCP Wrappers が効くのは libwrap でビルドされたサービス(sshd など、ただしビルド構成依存)と xinetd 配下のサービスに限られる。すべての通信を止めるものではないため、ネットワーク全体の遮断には iptables / nftables などのファイアウォールを併用する。

ログインと認証まわりの防御

サービスを絞ったら、ログインと認証も締める。/etc/nologin とシャドウパスワードが代表的。

/etc/nologin で一般ログインを止める

/etc/nologin ファイルが存在すると、root を除く一般ユーザーのログインが拒否される。ファイルの中身はログイン拒否時に表示されるメッセージになる。

echo "メンテナンス中です。後ほどお試しください。" > /etc/nologin

メンテナンス時に一時的にログインを封じる用途で使う。作業が終わったらファイルを削除すればログインが復活する。

シャドウパスワードの概要

シャドウパスワードは、暗号化済みパスワードを誰でも読める /etc/passwd から、root のみ読める /etc/shadow に分離する仕組み。現在のシステムでは標準で有効。

コマンド 動作
pwconv /etc/passwd からシャドウ化し /etc/shadow を生成
pwunconv /etc/shadow/etc/passwd に戻し shadow を削除
grpconv /etc/group から /etc/gshadow を生成
grpunconv /etc/gshadow/etc/group に戻し gshadow を削除

pwconv はパスワードを /etc/passwd から取り出し、該当フィールドを x に置き換える。pwunconv はその逆で、平文構成(実際は暗号化済みパスワードを passwd に戻す)にする。

レガシーな /etc/inittab は SysVinit 時代にデフォルトの実行レベル(runlevel)や各レベルで起動するプロセスを定義したファイル。systemd 環境では使われず、systemctl get-default / set-default でターゲット(旧 runlevel 相当)を管理する。試験では「inittab はレガシー」と位置づけを問われる。

よくあるミスと対処

ミス 1: stop だけで安心してしまう

systemctl stop は今のプロセスを止めるだけ。再起動すると enabled のサービスは再び立ち上がる。永続停止には disable(または disable --now)が必要。

ミス 2: mask と disable を混同する

disable は手動 start を許すが、mask は手動起動すら拒否する。「一時的に止めたいだけ」なのに mask すると、後で起動しようとして Unit is masked で詰まる。

ミス 3: hosts.allow と hosts.deny の評価順を逆に覚える

allow が先、deny が後。hosts.denyALL: ALL を書いても、hosts.allow で許可した接続は通る。「deny で全部閉じたのに入れてしまう」と慌てない。順序が仕様通りの正常動作。

ミス 4: ルールに何も書かず「閉じた」と思い込む

両ファイルが空、またはマッチするルールがなければデフォルトは許可。明示的に拒否するルールを書かない限り、TCP Wrappers は何も止めない。

ミス 5: TCP Wrappers が全サービスに効くと誤解する

効くのは libwrap 対応サービスと xinetd 配下のみ。Web サーバなど libwrap を使わないサービスは hosts.deny を無視する。全体の遮断はファイアウォールで行う。

トラブルシューティング

症状: disable したサービスが再起動後も動いている

原因: disable は自動起動の無効化のみで、稼働中プロセスは止めない。また socket ユニットや他サービスの依存で起動している可能性がある。

確認:

systemctl is-enabled svc
systemctl status svc

対処: systemctl disable --now svc で即時停止+無効化。socket 経由なら対応する svc.socket も停止・無効化する。

症状: hosts.allow に書いたのに接続が拒否される

原因: 対象サービスが libwrap 非対応、またはデーモン名の綴り違い。

確認:

ldd $(which sshd) | grep libwrap

対処: libwrap がリンクされていなければ TCP Wrappers は無効。ファイアウォール側で制御する。デーモン名はプロセス名(sshd 等)に正確に合わせる。

症状: mask したサービスに依存する別サービスが起動失敗する

原因: mask は依存解決を含めて起動を全拒否するため、依存元も連鎖的に失敗する。

確認:

systemctl list-dependencies --reverse svc

対処: 本当に不要かを再判断し、依存があるなら unmask して disable に切り替える。

作業完了チェックリスト

  • [ ] ss -tulnp でリッスン中サービスを洗い出した
  • [ ] 不要サービスを disable --now で停止・無効化した
  • [ ] 起動を完全に封じる対象は mask した
  • [ ] /etc/hosts.allow/etc/hosts.deny の順序を理解した
  • [ ] 必要に応じてファイアウォールを併用した

まとめ

目的 コマンド / ファイル ポイント
リッスン確認 ss -tulnp 0.0.0.0 は外部公開
即時停止 systemctl stop 再起動で復活
永続無効化 systemctl disable --now 実務の標準
起動ロック systemctl mask unmask まで起動不能
アクセス制御 /etc/hosts.allow / .deny allow→deny、最初のマッチで確定
ログイン停止 /etc/nologin root 以外を拒否

ホストセキュリティは「攻撃面を減らす」と「接続元を絞る」の二本柱。LPIC-1 110 系のセキュリティ範囲を一通り押さえたら、暗号化や権限管理と合わせて運用知識が完成する。

次に読む