ホストセキュリティ - 不要サービス停止/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「ホストのセキュリティを設定する」の中核。攻撃面(アタックサーフェス)を減らす「不要サービスの停止」と、接続元を絞る「アクセス制御」の二本柱を押さえる。
ホストセキュリティの基本方針とは
原則は「動いていないサービスは攻撃されない」。まず不要サービスを止め、残すサービスは接続元を絞る。この優先順位を間違えない。
ホストの堅牢化は次の順序で進めると漏れがない。
- 何がリッスンしているかを把握する(
ss -tulnp) - 不要なサービスを停止・無効化する(
systemctl) - 残すサービスへの接続元を制限する(TCP Wrappers / ファイアウォール)
- ログインや認証まわりを締める(
/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 |
ソケットを使うプロセスを表示 |
ss は iproute2 パッケージのコマンドで、レガシーな netstat -tulnp(net-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.conf の defaults ブロックには全サービス共通の設定(ログ形式・接続数上限など)を書く。
現在のディストリビューションは systemd ソケットアクティベーション(.socket ユニット)が xinetd の役割を引き継いでいる。試験では inetd / xinetd の概念と設定ファイル位置を問われる。
TCP Wrappers のアクセス制御を理解するには
TCP Wrappers は libwrap でリンクされたサービスへの接続を、ホスト単位で許可・拒否する仕組み。/etc/hosts.allow と /etc/hosts.deny の 2 ファイルで制御する。
評価順序(最重要)
公式マニュアル hosts_access(5) によると、判定は次の順で行われ、最初にマッチしたルールで確定する(first match wins)。
/etc/hosts.allowを上から検索。マッチすれば許可して終了。- マッチしなければ
/etc/hosts.denyを検索。マッチすれば拒否して終了。 - どちらにもマッチしなければ許可(デフォルト許可)。
つまり 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.allow で sshd への 192.168.1.0/24 と 10.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.deny に ALL: 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 系のセキュリティ範囲を一通り押さえたら、暗号化や権限管理と合わせて運用知識が完成する。