LFCS — Linux Foundation認定システム管理者
SELinux と firewalld を手で — そしてユーザー・ACL・sshd・dnf
目標
AlmaLinux 9のVMで、SELinuxのブーリアン・ファイルコンテキスト・ポートコンテキストを実際に設定し、firewalldのruntime/permanentとゾーン・リッチルールを手で扱い、ユーザー・sudoers・profile.d・limits・ACL・sshdドロップイン・dnfのロックを、結果が残るように構成します。
なぜ重要なのか
LFCSのOperationsドメインは「SELinuxでアクセスを管理せよ」を明示し、Networkingドメインは、パケットフィルタリングとOpenSSHを要求します。PodにはSELinuxもfirewalldもないので、これらの項目は、模擬試験でかすめた程度でした。このVMはEnforcingで、firewalldが動いているので、ポートコンテキストを書き漏らすと、httpdが本当に起動せず、permanentを書き漏らすと、reloadした瞬間にルールが消えます。
3つが繰り返されます。1つ目、今の値と永続の値は、別の場所にあります。setseboolの-P、chconとsemanage fcontext、firewalldのruntimeとpermanent。2つ目、実効値は、ファイルではなくツールが教えてくれます。sshd -T、getsebool、sudo -l -U、getfacl。3つ目、締め出されないように、検査から。visudo -cf、sshd -t、apachectl configtest。
⚠️ 採点エージェントが8899/tcpで入ってきます。firewalldを触るときに、このポートを消したり、デフォルトのゾーンをdropに変えたりすると、採点が届かず、次のステップから原因不明の失敗になります。セッションは60分で始まり、最大180分まで延長でき、VMはセッションが終わると消えます。
ステップ
sestatusの出力を/root/lfcs/selinux/status.txtに保存してください(Enforcingである必要があります)。そして、ブーリアンhttpd_can_network_connectを、再起動後も維持されるように有効にしてください。/srv/web/index.htmlにselinux okと書き、/srv/web以下が永続的にhttpd_sys_content_tコンテキストを持つようにしてから、適用してください(semanage fcontext + restorecon)。tcp 8081をhttp_port_tとして登録し、/etc/httpd/conf.d/lfcs.confで、httpdが8081で/srv/webを提供するようにして、enable・startしてください。curl http://127.0.0.1:8081/がselinux okを返す必要があります。- デフォルトゾーン(public)に、サービス
httpとポート8081/tcpを、runtimeとpermanentの両方に開けてください。採点用のポート8899/tcpは、そのままである必要があります。最後に、firewall-cmd --list-allの出力を/root/lfcs/firewall/public.txtに保存してください。 - ゾーン
labを新しく作成して、送信元198.51.100.0/24をそのゾーンに割り当ててください。labゾーンに、サービスsshと、198.51.100.0/24から来るtcp 8081を許可するリッチルール(rule family="ipv4" source address="198.51.100.0/24" port port="8081" protocol="tcp" accept)を入れてください。すべてpermanentで書いてreloadし、runtimeにも表示される必要があります。 - グループ
opsを作成し、ユーザーdeploy(ホームディレクトリあり、シェル/bin/bash)を作成して、補助グループとしてopsに入れてください。/etc/sudoers.d/opsに、opsグループがパスワードなしで/usr/bin/systemctlだけをsudoで実行できるルールを書き、権限を0440にしてください。visudo -cfで、文法チェックが通る必要があります。 /etc/profile.d/lfcs.shで、環境変数LFCS_ENVをlabにexportしてください。/etc/security/limits.d/90-lfcs.confに、ユーザーdeployの開けるファイル数(nofile)のhard上限を4096に、グループopsのプロセス数(nproc)のsoft上限を2048に、書いてください。su - deployでログインシェルを開いたとき、envに変数が見え、ulimit -Hnが4096である必要があります。/srv/web/uploadディレクトリを、root所有、権限750で作成し(chmodで広げません)、ACLでユーザーdeployにrwxを、そして、このディレクトリの中に新しくできるファイルが、グループopsにr-xを引き継ぐように、デフォルト(default)ACLを与えてください。getfacl /srv/web/uploadの出力を/root/lfcs/acl/upload.aclに保存してください。(ACLを与えたあと、ls -ldのグループの位置は、マスク(rwx)で表示されます。正常です。)/etc/ssh/sshd_config.d/50-lfcs.confのドロップインに、MaxAuthTries 3、ClientAliveInterval 300、PermitRootLogin noを書いて、sshdを再起動してください。sshd -Tで見た最終的な値が、3つともその値である必要があります。treeパッケージをインストールし、アップグレードから除外されるように、versionlockでロックするか、/etc/dnf/dnf.confのexclude=に入れてください。dnf history listの出力を/root/lfcs/pkg/history.txtに、rpm -q treeの出力を/root/lfcs/pkg/tree.txtに保存してください。
参考
- SELinux:
getenforce、setsebool -P、semanage fcontext -a -t … '/경로(/.*)?'→restorecon -Rv、semanage port -a -t http_port_t -p tcp 8081。拒否の記録はausearch -m avc -ts recent(プレースホルダーはパスです)。 - firewalld:
--permanentで書いて--reload。--zone=lab --list-allで、ゾーン1つを丸ごと見ます。 - ユーザー:
useradd -m -s /bin/bash -G ops deploy、visudo -cf /etc/sudoers.d/ops、sudo -l -U deploy。 - limitsは、ログインの瞬間にかかります。すでに開いているシェルで
ulimitを見ても、変わりません。 - よくある間違い1:
chconでコンテキストを変更して終わりにする場合です。restorecon1回で元に戻ります。 - よくある間違い2: firewalldのルールをruntimeにだけ入れて、
--reloadして消してしまう場合です(reloadはpermanentを読み直します)。 - よくある間違い3: profile.dで
exportを抜かして、シェル変数としてだけ残る場合です。
SELinuxのモード確認とブーリアン
sestatusの出力を/root/lfcs/selinux/status.txtに保存してください(Enforcingである必要があります)。そして、ブーリアンhttpd_can_network_connectを、再起動後も維持されるように有効にしてください。
setseboolに-Pを付けると、ポリシーストアに記録されます。確認は、getseboolとsemanage boolean -l -C(ローカルの変更だけを表示)です。
ファイルコンテキストとポートコンテキストでhttpdを8081に
/srv/web/index.htmlにselinux okと書き、/srv/web以下が永続的にhttpd_sys_content_tコンテキストを持つようにしてから、適用してください(semanage fcontext + restorecon)。tcp 8081をhttp_port_tとして登録し、/etc/httpd/conf.d/lfcs.confで、httpdが8081で/srv/webを提供するようにして、enable・startしてください。curl http://127.0.0.1:8081/がselinux okを返す必要があります。
chconは、restoreconすると消えます。semanage fcontext -a -t <タイプ> '/srv/web(/.*)?'が永続です。ポートを登録しないと、httpdが8081をbindできず、起動自体が失敗します(journalctl -u httpdとausearch -m avcで確認)。
firewalldのサービスとポート: runtimeとpermanent
デフォルトゾーン(public)に、サービスhttpとポート8081/tcpを、runtimeとpermanentの両方に開けてください。採点用のポート8899/tcpは、そのままである必要があります。最後に、firewall-cmd --list-allの出力を/root/lfcs/firewall/public.txtに保存してください。
--permanentを付けるとファイルにだけ、付けないと今動いているルールにだけ適用されます。両方行うか、--permanentで書いて--reloadしてください。確認は--list-services / --permanent --list-services。
新しいゾーンとリッチルール
ゾーンlabを新しく作成して、送信元198.51.100.0/24をそのゾーンに割り当ててください。labゾーンに、サービスsshと、198.51.100.0/24から来るtcp 8081を許可するリッチルール(rule family="ipv4" source address="198.51.100.0/24" port port="8081" protocol="tcp" accept)を入れてください。すべてpermanentで書いてreloadし、runtimeにも表示される必要があります。
新しいゾーンは--permanent --new-zone=labでしか作れず、reloadしてはじめてruntimeに現れます。--zone=lab --add-source=...、--add-service=...、--add-rich-rule='...'。確認は--zone=lab --list-all。
グループ・ユーザー・sudoersのルール
グループopsを作成し、ユーザーdeploy(ホームディレクトリあり、シェル/bin/bash)を作成して、補助グループとしてopsに入れてください。/etc/sudoers.d/opsに、opsグループがパスワードなしで/usr/bin/systemctlだけをsudoで実行できるルールを書き、権限を0440にしてください。visudo -cfで、文法チェックが通る必要があります。
useradd -m -s /bin/bash -G ops deploy。sudoersの1行: %ops ALL=(ALL) NOPASSWD: /usr/bin/systemctl。文法が間違っていると、sudo全体がロックされるので、必ずvisudo -cfで検査します。sudo -l -U deployで結果を見ます。
ログイン環境とリソース制限
/etc/profile.d/lfcs.shで、環境変数LFCS_ENVをlabにexportしてください。/etc/security/limits.d/90-lfcs.confに、ユーザーdeployの開けるファイル数(nofile)のhard上限を4096に、グループopsのプロセス数(nproc)のsoft上限を2048に、書いてください。su - deployでログインシェルを開いたとき、envに変数が見え、ulimit -Hnが4096である必要があります。
profile.dは、ログインシェルが/etc/profileを経由して読み込みます。exportがないと、子プロセス(env)に見えません。limitsの行は「対象 種類 項目 値」の4つのフィールドで、グループは@opsです。pam_limitsがログイン時に適用します。
ACLで所有権の外の権限を与える
/srv/web/uploadディレクトリを、root所有、権限750で作成し(chmodで広げません)、ACLでユーザーdeployにrwxを、そして、このディレクトリの中に新しくできるファイルが、グループopsにr-xを引き継ぐように、デフォルト(default)ACLを与えてください。getfacl /srv/web/uploadの出力を/root/lfcs/acl/upload.aclに保存してください。(ACLを与えたあと、ls -ldのグループの位置は、マスク(rwx)で表示されます。正常です。)
setfacl -m u:deploy:rwx <ディレクトリ>、デフォルトACLはsetfacl -d -m g:ops:rx(または-m d:g:ops:rx)。ls -lに+が付いていれば、ACLがあります。マスク(mask)の行が実効権限を削ります。
sshdのドロップインとsshd -T
/etc/ssh/sshd_config.d/50-lfcs.confのドロップインに、MaxAuthTries 3、ClientAliveInterval 300、PermitRootLogin noを書いて、sshdを再起動してください。sshd -Tで見た最終的な値が、3つともその値である必要があります。
sshd_configのIncludeは一番上にあるので、ドロップインが本体より先に読まれ、sshdは同じキーの最初の値を使います。sshd -tで文法、sshd -Tで実効値。コンソール接続はsshdと無関係なので、締め出される心配はありません。
dnfのインストール・ロック・履歴
treeパッケージをインストールし、アップグレードから除外されるように、versionlockでロックするか、/etc/dnf/dnf.confのexclude=に入れてください。dnf history listの出力を/root/lfcs/pkg/history.txtに、rpm -q treeの出力を/root/lfcs/pkg/tree.txtに保存してください。
versionlockプラグインはすでにインストールされています: dnf versionlock add tree / dnf versionlock list。excludeは、dnf.confの[main]節のexclude=tree。historyはトランザクション単位なので、インストールが1行で見えます。