「pingコマンドをrootでなければ実行できなくなっている──なぜ?」
こうした疑問の答えが、Linuxのcapabilities(ケーパビリティ)という仕組みにあります。Linuxが「rootかそれ以外か」の二択から脱却するために Linux 2.2 で導入された機能で、root権限を約40種類の独立した特権(capability)に分割します。
setcapコマンドで実行ファイルに必要なcapabilityだけを付与すれば、フルのroot権限を与えなくても特権操作を安全に委任できます。この記事では、
setcap・getcapコマンドの使い方から、systemdのAmbientCapabilities・CapabilityBoundingSetによる本番サービスへの適用まで、実際のサーバーでの出力例とともに解説します。RHEL 9 / Rocky Linux 9 / Ubuntu 24.04 LTSで動作確認済みです。この記事のポイント
・setcapでCAP_NET_BIND_SERVICEを付与すれば、root不要で80/443番ポートへのバインドができる
・getcapで現在のファイルケーパビリティを確認し、setcap -r でいつでも取り消せる
・systemdのAmbientCapabilitiesを使うとパッケージ更新後もケーパビリティ設定が維持される
・CAP_SYS_ADMINのような広大なcapabilityは最終手段──他のcapabilityで代替できないか先に検討する
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
Linuxのcapabilitiesとは何か(root権限を分割する仕組み)
昔のUnix系OSは「root(UID=0)かそれ以外か」の二択でした。root以外のプロセスが1024番未満のポートにバインドしようとすると「Permission denied」になり、rawソケットを使おうとしても同様でした。このため、一部の特権操作しか必要がなくても、サービスをrootとして起動するか、setuid rootのバイナリを使うしかありませんでした。setuid rootには問題があります。ファイルにsetuidビットが立っていると、プロセスはフルのroot権限で動きます。脆弱性が発見された場合、攻撃者は一気にrootを手に入れられます。
これを解決するために Linux 2.2(1999年)でPOSIXケーパビリティが導入されました。現在のLinuxカーネルには約40種類のcapabilityが定義されており、ケーパビリティはプロセスごと・ファイルごとに設定できます。
・プロセスのケーパビリティセット:
Effective(実際に有効)・Permitted(保持できる上限)・Inheritable(exec後に子プロセスに引き継げる)の3種・ファイルのケーパビリティセット:
Effectiveビット・Permittedセット・Inheritableセット。setcapコマンドで設定し、拡張属性(xattr)としてファイルシステムに保存される「ファイルにケーパビリティが設定されている実行ファイルを非rootユーザーが実行すると、そのcapabilityだけが有効になる」──これがsetcapによる最小権限設計の核心です。
主要なcapabilityの種類と用途
Linuxのcapabilityは約40種類ありますが、現場でよく使う代表的なものを以下に整理します。| Capability名 | できること | 代表的な用途 |
|---|---|---|
CAP_NET_BIND_SERVICE |
1024番未満のポートにバインド | node.js / Python で80/443番を非rootで起動 |
CAP_NET_RAW |
rawソケット・パケットソケットの使用 | ping・traceroute・arpingを非rootで実行 |
CAP_NET_ADMIN |
ネットワーク設定の変更(ルーティング・インターフェース操作等) | tcコマンド・ip routeの変更 |
CAP_DAC_OVERRIDE |
ファイルパーミッションのDAC制限を無視 | どのファイルでも読み書き可(危険。他のcapで代替を検討) |
CAP_SETUID |
任意のUIDへの切り替え | sudo・su等の特権昇格ツール |
CAP_SYS_ADMIN |
非常に広範な操作(マウント・sysctl変更等) | 最後の手段。他のcapabilityで代替を先に検討する |
CAP_AUDIT_WRITE |
カーネル監査ログへの書き込み | PAM認証ログ記録 |
CAP_CHOWN |
ファイルのUID/GIDを任意に変更 | バックアップツール・デプロイスクリプト |
CAP_SYS_ADMINは最終手段にします。「CAP_SYS_ADMINを付ければ動く」という解決策は、事実上フルroot権限に近い権限を与えることになり、最小権限の原則に反します。getcapコマンドでファイルのケーパビリティを確認する
1. libcap をインストールする
getcap・setcapコマンドはlibcapパッケージに含まれています。まず以下でインストール済みか確認します。# RHEL 9 / Rocky Linux 9 でインストール確認 [user@server01 ~]$ rpm -q libcap libcap-2.48-9.el9_2.x86_64 # 入っていない場合はインストールする [root@server01 ~]# dnf install -y libcap # Ubuntu 24.04 LTS でインストール確認 user@ubuntu:~$ dpkg -l libcap2-bin ii libcap2-bin 1:2.66-5ubuntu2 amd64 POSIX 1003.1e capabilities (utilities) # Ubuntu でインストールする場合 sudo apt install libcap2-bin
2. getcap コマンドでファイルのケーパビリティを確認する
getcap ファイルパスで、対象ファイルに設定されているケーパビリティを表示します。# ping のケーパビリティを確認する(Rocky Linux 9) [user@server01 ~]$ getcap /usr/bin/ping /usr/bin/ping cap_net_admin,cap_net_raw=p # Python 3 にケーパビリティが設定されていない状態 [user@server01 ~]$ getcap /usr/bin/python3 (出力なし = ケーパビリティ未設定) # システム全体でケーパビリティが設定されているファイルを一括検索 [user@server01 ~]$ sudo getcap -r / 2>/dev/null /usr/bin/ping cap_net_admin,cap_net_raw=p /usr/bin/python3.12 cap_net_bind_service=ep
=p・=ep・=eip)はケーパビリティセットを表します。・=p(permitted):バイナリ実行時にそのcapabilityを保持できるが、コード側で明示的に有効化する必要がある
・=ep(effective + permitted):実行開始時から即座に有効。ほとんどの実用ケースではこれを使う
・=eip(effective + inheritable + permitted):さらに子プロセスへの引き継ぎも有効になる
setcapコマンドでケーパビリティを付与する実践手順
1. CAP_NET_BIND_SERVICE の付与(80番ポートを非rootで使う)
Pythonの組み込みHTTPサーバーをポート80で非rootユーザーとして起動する例です。setcapはroot権限で実行する必要があります。# Python 3 インタープリターにCAP_NET_BIND_SERVICEを付与する [root@server01 ~]# setcap cap_net_bind_service=ep /usr/bin/python3.12 # 設定を確認する [root@server01 ~]# getcap /usr/bin/python3.12 /usr/bin/python3.12 cap_net_bind_service=ep # 一般ユーザーで80番ポートに起動できるか確認する [user@server01 ~]$ python3 -m http.server 80 Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ... # 別ターミナルでポートの確認 [user@server01 ~]$ ss -tlnp | grep ':80' LISTEN 0 5 0.0.0.0:80 0.0.0.0:* users:(("python3",pid=12345,fd=3))
ss -tlnpの出力でプロセスが一般ユーザー権限で80番ポートをListenしていることが確認できます。Linux ポート確認の全コマンドも参照してください。2. CAP_NET_RAW の付与(ping を非rootで実行できるようにする)
セキュリティポリシーでpingのsetuidビットを落とした環境では、capabilityで代替できます。# 現在のpingのケーパビリティを確認する [user@server01 ~]$ getcap /usr/bin/ping /usr/bin/ping cap_net_admin,cap_net_raw=p # ケーパビリティが外れていて非rootでは実行できない場合に付与する [root@server01 ~]# setcap cap_net_raw+ep /usr/bin/ping [root@server01 ~]# getcap /usr/bin/ping /usr/bin/ping cap_net_raw=ep # 一般ユーザーでpingが打てることを確認する [user@server01 ~]$ ping -c 3 192.168.1.1 PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data. 64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=0.412 ms 64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=0.398 ms 64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=0.411 ms --- 192.168.1.1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2051ms
3. ケーパビリティを削除する方法
設定したケーパビリティを取り除くにはsetcap -rを使います。# ケーパビリティを削除する(-r オプション) [root@server01 ~]# setcap -r /usr/bin/python3.12 # 削除後の確認(出力がなければ削除済み) [root@server01 ~]# getcap /usr/bin/python3.12 (出力なし)
systemdサービスのCapabilities設定(AmbientCapabilities・CapabilityBoundingSet)
ファイルへのsetcapは手軽ですが、パッケージアップデートでバイナリが更新されるたびに再設定が必要になります。systemdのunit fileでCapabilitiesを管理すれば、バイナリを更新しても設定が維持されます。1. AmbientCapabilitiesとは
Linux 4.3 で追加されたAmbient Capabilitiesは、プロセスがexecした子プロセスに自動的にcapabilityを引き継がせる仕組みです。systemdのunit fileでAmbientCapabilities=に指定すると、そのサービスのプロセスと子プロセス全体にcapabilityが付与されます。ファイル側にsetcapが設定されていなくても機能します。2. systemd unit fileにAmbientCapabilitiesを設定する
/usr/bin/python3でWebサーバーを80番ポートで起動するサービスの例です。# /etc/systemd/system/mywebserver.service [Unit] Description=My Web Server on Port 80 After=network.target [Service] Type=simple User=webuser Group=webuser # 80番ポートバインドに必要なcapabilityだけを付与する AmbientCapabilities=CAP_NET_BIND_SERVICE # プロセスがexecで新たに特権を取得できないようにする NoNewPrivileges=true # AmbientCapabilitiesが有効になるよう上限セットも明示する CapabilityBoundingSet=CAP_NET_BIND_SERVICE ExecStart=/usr/bin/python3 -m http.server 80 [Install] WantedBy=multi-user.target
# unit fileを読み込んで起動する [root@server01 ~]# systemctl daemon-reload [root@server01 ~]# systemctl enable --now mywebserver # プロセスのcapabilityを /proc で確認する [root@server01 ~]# PID=$(systemctl show mywebserver --property=MainPID --value) [root@server01 ~]# grep -i cap /proc/${PID}/status CapInh: 0000000000000400 CapPrm: 0000000000000400 CapEff: 0000000000000400 CapBnd: 0000000000000400 CapAmb: 0000000000000400
0000000000000400は16進数で、CAP_NET_BIND_SERVICE(ビット10=0x400)のみが有効な状態を表します。他のcapabilityがすべて0になっており、最小権限で稼働していることが読み取れます。3. CapabilityBoundingSetとNoNewPrivilegesの役割
・CapabilityBoundingSet:プロセスが持てるcapabilityの上限(境界)を制限します。ここに含まれないcapabilityはexec後に一切取得できません・NoNewPrivileges:trueにするとsetuidビットやexecによるcapability昇格が無効になります。コンテナセキュリティでも必須とされる設定です
AmbientCapabilities・CapabilityBoundingSet・NoNewPrivilegesの3点セットで設定することで、サービスが必要最小限のcapabilityだけを持ち、かつそれ以上に昇格できない設計が完成します。ケーパビリティ付与後のよくあるエラーと対処法
1. 「Operation not permitted」がまだ出る場合
setcapは正常に通ったのに起動するとPermission deniedになる場合、以下を確認します。・シンボリックリンクへのsetcap:
setcapはシンボリックリンクに付与しても無効です。ls -laで実体ファイルのパスを確認し、そちらに付与してください・NFSやnoexecマウント:NFS経由のファイルシステムや
noexecオプション付きでマウントされた領域ではケーパビリティが無効になります・SELinuxの拒否:SELinuxが有効な環境では、
ausearch -m AVC -ts recentでSELinuxの拒否ログを確認します# シンボリックリンクか実体かを確認する [root@server01 ~]# ls -la /usr/bin/python3 lrwxrwxrwx 1 root root 9 1月 9 10:23 /usr/bin/python3 -> python3.12 # シンボリックリンク先の実体ファイルに対してsetcapを実行する [root@server01 ~]# setcap cap_net_bind_service=ep /usr/bin/python3.12 [root@server01 ~]# getcap /usr/bin/python3.12 /usr/bin/python3.12 cap_net_bind_service=ep
2. パッケージ更新後にケーパビリティが消える
dnf updateやapt upgradeでバイナリが新しいバージョンに置き換わると、setcapで設定したxattr情報も消えます。・短期対策:更新後に
setcapを再実行する・長期対策:前節のsystemd
AmbientCapabilities方式へ移行する(バイナリ側でなくunit file側で管理するため更新の影響を受けない)3. シェルスクリプトに setcap できない
シェルスクリプト(#!/bin/bash)に直接setcapを設定しようとすると以下のエラーが出ます。[root@server01 ~]# setcap cap_net_bind_service=ep /usr/local/bin/myscript.sh Failed to set capabilities on file '/usr/local/bin/myscript.sh' (Invalid argument)
/bin/bash・/usr/bin/python3等)に付与するか、systemdのAmbientCapabilities方式を使います。本記事のまとめ
| やりたいこと | コマンド・設定 |
|---|---|
| ファイルのケーパビリティを確認する | getcap /usr/bin/python3.12 |
| システム全体でケーパビリティ設定済みを検索 | sudo getcap -r / 2>/dev/null |
| 80番ポートバインドを非rootで許可する | setcap cap_net_bind_service=ep /usr/bin/python3.12 |
| pingを非rootで使えるようにする | setcap cap_net_raw+ep /usr/bin/ping |
| ケーパビリティを削除する | setcap -r /usr/bin/python3.12 |
| systemdサービスに最小権限を持たせる | unit fileにAmbientCapabilities=CAP_NET_BIND_SERVICE |
| capabilityの昇格を禁止する | unit fileにNoNewPrivileges=true |
setcapによる最小権限設計は、「rootかそれ以外か」という二択から脱却する実践的なアプローチです。特にシステムサービスではsystemdのAmbientCapabilitiesとCapabilityBoundingSetを組み合わせることで、パッケージ更新後も設定が維持される堅牢な権限管理が実現できます。CAP_SYS_ADMINのような広大なcapabilityに頼らず、本当に必要な権限だけを最小限で付与するという設計思想は、Linuxサーバーの長期運用においてセキュリティリスクを抑える上で非常に重要です。
capabilitiesで最小権限設計を身につけたら、次はLinuxサーバー全体のセキュリティ設計をプロのレベルで固めませんか?
ケーパビリティはLinuxセキュリティ設計の重要な一要素です。setuid・sudoers・SELinux・ファイアウォールと組み合わせて体系的に理解することで、本番環境で安全なサーバーを設計・運用できる力が身につきます。
ネットの切れ端の情報をコピペするだけでなく、現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:perfコマンドでLinuxのCPUホットスポットを特定する方法|perf record・perf reportでボトルネックを調査する実践手順
- この記事の属するカテゴリ:Linuxtips・セキュリティへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます