Info: Version 1.8.x is available.
Last modified: $Date: 2024-03-31 15:45:12 +0000 (Sun, 31 Mar 2024) $
これまでの連載では,ファイルに対するアクセス制御機能について紹介してきました.ファイルに対するアクセス制御機能は,プログラムやデータへの不要なアクセスを排除する,セキュアOSを用いたセキュリティ強化の基本となります.しかし,この機能だけでは十分とは言えません.今回は, TOMOYO Linux が備える他のアクセス制御機能の中からネットワークに対するアクセス制御機能をはじめ主要なものを紹介します.
Linux ではデフォルトで iptables というパケットフィルタリングを行うための機能が利用できます. TOMOYO Linux でも同様の機能を提供しますが, TOMOYO Linux のネットワークに対するアクセス制御機能はドメイン単位やユーザID単位でパケットフィルタリングを行うことができ,設定も容易です. iptables の設定は構文が難しくてわからないという人でも使えます(ただし, iptables と連携しているわけではないので, iptables でしか利用できない機能もあります.).
TOMOYO Linux におけるネットワーク制御の対象について図1に示します.
■図1 ネットワーク制御の対象
TCPプロトコル/UDPプロトコル/IPプロトコル IPv4ネットワークアドレス/IPv6ネットワークアドレス ポート番号 |
TOMOYO Linux のネットワークアクセス制御機能を用いると,たとえば「 /usr/sbin/sshd からログインしたユーザIDが 500 のユーザが実行した svn プロセスのみが,ホスト 202.221.179.11 のポート 80 に対してTCPプロトコルを用いた通信を行うことができる」といった制御が可能となります.次節以降,実際に設定してみることにしましょう.
ネットワークに対するアクセス制御はファイルに対するアクセス制御と同様にドメイン毎に指定ができます.ここでは,「ネットワークアクセス制御のみの学習」「ネットワークアクセス制御のみの確認」「ネットワークアクセス制御のみの強制」の3種類のプロファイルを作ります.
準備としてプロファイル5~7を作成することにします. /etc/ccs/profile.conf の末尾に図2の内容を追加してください.
■図2 /etc/ccs/profile.conf の末尾に追加する内容
5-COMMENT=Learning Mode (Network Only) 5-CONFIG::network={ mode=learning } 6-COMMENT=Permissive Mode (Network Only) 6-CONFIG::network={ mode=permissive } 7-COMMENT=Enforcing Mode (Network Only) 7-CONFIG::network={ mode=enforcing } |
保存したら,図3のコマンドを実行して変更を反映してください.
■図3 変更を反映する
# /usr/sbin/ccs-loadpolicy p |
学習させるドメインの範囲は任意ですが,今回は操作中のシェルが属しているドメイン以下を対象としましょう.現在のプロセスが属しているドメイン名は, /proc/ccs/self_domain の内容を /bin/cat コマンドで表示するとわかります.もし,現在実行中のシェルが keep_domain によりドメイン遷移を行わないように指定されていた場合は,ポリシーエディタを用いて一時的に keep_domain の指定を削除してください(ポリシーエディタで表示する際に見やすくするためであり,実環境で利用する場合には keep_domain の指定を削除する必要はありません.).なお,学習されるIPアドレスやポート番号は環境により異なりますのでご了承ください.
図4の内容を実行し,現在のプロセスの属しているドメイン以下を学習モードにします(リダイレクトの部分は,実際のドメイン名を文字列として引用しても結構です).
■図4 現在のプロセスが属しているドメイン以下を学習モードにする
# xargs -0 /usr/sbin/ccs-setprofile -r 5 < /proc/ccs/self_domain |
学習させるためのコマンドとして,ここでは /usr/bin/curl コマンドを用いて http://www.osdn.jp/ にアクセスしてみます(図5).
■図5 /usr/bin/curl コマンドを学習させる
# curl http://www.osdn.jp/ > /dev/null |
なお, /usr/bin/curl コマンドが使えない場合は, /usr/bin/wget や /usr/kerberos/bin/telnet などでもかまいません.ポリシーエディタを起動して, /usr/bin/curl コマンドを実行したドメインのアクセス許可を表示してみましょう(図6).
■図6 /usr/bin/curl コマンドを実行したドメインのアクセス許可 |
allow_network で始まる行が,ネットワークに対するアクセス制御のためのアクセス許可です.「 allow_network UDP connect 192.168.1.2 53 」という部分は,UDPプロトコルを用いてDNSサーバ 192.168.1.2 のポート 53 にアクセスすることを許可するという意味です.また,「 allow_network TCP connect 202.221.179.11 80 」という部分は,TCPプロトコルを用いてHTTPサーバ 202.221.179.11 (本稿執筆時点の www.osdn.jp のIPアドレスです)のポート 80 にアクセスすることを許可するという意味です.
今度は,/usr/bin/ssh コマンドを用いてSSHサービスにログインしてみます(SSHサービスを稼動させていない場合には,HTTPなどの他のサービスでもかまいません).例外ポリシーで「 initialize_domain /usr/sbin/sshd 」という指定がされている場合(連載第1回で実行した init_policy によりそのように指定されているはずです), /usr/sbin/sshd は「 <kernel> /usr/sbin/sshd 」というドメインで動作することになるので,そのドメインに学習用のプロファイルを割り当ててみます(図7).
■図7 <kernel> /usr/sbin/sshd ドメインに学習用プロファイルを割り当てる
# /usr/sbin/ccs-setprofile 5 '<kernel> /usr/sbin/sshd' |
その後,SSHで localhost にログインし(図8),ポリシーエディタを実行して <kernel> /usr/sbin/sshd ドメインに対するアクセス許可を確認してください(図9).
■図8 SSHで localhost にログイン
# ssh localhost |
■図9 <kernel> /usr/sbin/sshd ドメインに対するアクセス許可 |
「 allow_network TCP accept 0:0:0:0:0:ffff:7f00:1 34561 」という部分は, 0:0:0:0:0:ffff:7f00:1 というIPv6アドレスを持つホストのポート 34561 からのTCPコネクションを受け付けることを許可するという意味です.
ファイルに対するアクセス許可と同様に,ネットワークに対するアクセス許可にも条件を付与することができます.たとえば,図10のようにプロセスのユーザIDと組み合わせることで,ユーザごとに接続可能なサーバを制限したりすることもできます.
■図10 ユーザごとに接続可能なサーバを制限
allow_network TCP connect 202.221.179.11 80 if task.uid=500 allow_network TCP connect 66.35.250.203 80 if task.uid=501 |
IPソケットの場合には,ポート番号の代わりにプロトコル番号を指定します. ping コマンドを例に説明します.図11の内容を実行してから,ポリシーエディタで ping コマンドの動作するドメインに対するアクセス許可を確認してください(図12).
■図11 ping コマンドを実行
# ping -c 4 www.osdn.jp |
■図12 ping コマンドの動作するドメインに対するアクセス許可 |
「 allow_network RAW connect 202.221.179.11 1 」というアクセス許可が与えられていることを確認できます.これは, ping コマンドが動作しているドメインではIPソケット上でプロトコル番号1のプロトコル( ICMP )を用いて 202.221.179.11 と通信を行うことを許可するという意味です.
ひととおり学習してみたら,確認モードに切り替えて確認してみましょう.確認モードにするにはプロファイル6を割り当てます(図13).
■図13 プロファイル6を割り当て,確認モードに切り替え
# xargs -0 /usr/sbin/ccs-setprofile -r 6 < /proc/ccs/self_domain |
ファイルに対するアクセス制御を行う際にワイルドカードを用いてパターン化したように,ネットワークに対するアクセス制御を行う際にもパターン化が必要になります.パターン化を行う場合は,開始アドレスと終了アドレスを-を用いて図14のように指定してください.-の前後に空白を入れてはいけません.
■図14 IPv4アドレスを範囲で指定する
xxx.xxx.xxx.xxx-yyy.yyy.yyy.yyy |
IPv6アドレスによる指定もIPv4アドレスの場合と同様ですが,「 :: 」という省略表記や「 . 」混じりの表記はサポートしていません.つねに図15のような形式で指定する必要があります.その他,負荷分散のため複数のIPアドレスを持つサーバに対するアクセス許可を与える場合は,使う可能性のあるすべてのIPアドレスを指定することを忘れないでください.
■図15 IPv6アドレスを指定する
xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx |
サーバがクライアントからのリクエストを受け付けるためのポート番号は一般に固定されているのに対し,クライアントがリクエストを送り出すときに使用するポート番号は固定されていません.そのため,サーバ側でクライアントが使用する可能性のあるポート番号を範囲としてパターン化してやる必要があります.パターン化を行う場合は,開始ポートと終了ポートを-を用いて図16のように指定してください.-の前後に空白を入れてはいけません.よくあるパターンは図17の3つです.
■図16 ポート番号を範囲で指定する
xxxxx-yyyyy |
■図17 ポート番号パターン化の例
1024-65535 32768-61000 600-1023 |
最初のパターンは通常のクライアントがサーバに接続する際に選択する可能性がある範囲で,おもにサーバ側のプログラムで必要になります.2番目のパターンは「 /proc/sys/net/ipv4/ip_local_port_range 」に指定されているポート番号の範囲です.通常のクライアントはこの範囲から未使用のローカルポート番号を選択してサーバに接続するため,おもにクライアント側のプログラムで必要になります.実際の /proc/sys/net/ipv4/ip_local_port_range の内容に合わせてパターンを定義してください.
最後のパターンは, portmap コマンドのように未使用の特権ポート(ポート番号が 1024 未満のポート)を選択して接続するプログラムで必要になります.実際に必要な範囲は異なる場合があります.パターン化が必要か否かを判断する簡単な方法は,プログラムを何度か実行してみることです.たとえば,学習モードで何度か実行すると,図18のように,ポート番号が連続するアクセス許可が増えていきますので,その傾向から必要な範囲を推測してください.
■図18 ポート番号が連続するアクセス許可の例①
allow_network TCP bind 127.0.0.1 610 allow_network TCP bind 127.0.0.1 611 allow_network TCP bind 127.0.0.1 612 allow_network TCP bind 127.0.0.1 613 |
図18の例の場合,図19のような許可が必要である可能性が高いと言えます.
■図19 図18を元にパターン化したアクセス許可
allow_network TCP bind 127.0.0.1 600-1023 |
また,図20であれば,図21または図22という許可が必要である可能性が高いでしょう.
■図20 ポート番号が連続するアクセス許可の例②
allow_network TCP accept 127.0.0.1 32780 allow_network TCP accept 127.0.0.1 32781 allow_network TCP accept 127.0.0.1 32782 allow_network TCP accept 127.0.0.1 32783 allow_network TCP accept 127.0.0.1 32784 |
■図21 図20を元にパターン化したアクセス許可
allow_network TCP accept 127.0.0.1 1024-65535 |
■図22 図20を元にパターン化したアクセス許可
allow_network TCP accept 127.0.0.1 32768-61000 |
確認が終わったら,実際にネットワークのアクセス制御を適用しましょう.強制モードにするにはプロファイル7を割り当てます(図23).
■図23 プロファイル7を割り当て,強制モードを適用
# xargs -0 /usr/sbin/ccs-setprofile -r 7 < /proc/ccs/self_domain |
なお,プロファイル5~7はファイルに関するアクセス制御を行っていないことに注意してください.本連載の4回目で紹介した,対話的にアクセス許可を追加する ccs-queryd を用いることで,その場で不足しているアクセス許可を追加することもできます. TOMOYO Linux を使うと, iptables 単体で行えるネットワークアクセス制御の内容を細分,詳細化できることがご理解いただけると思います.
Linux カーネル 2.2 以降では POSIX ケイパビリティに対応しています.ケイパビリティは,セキュアOSの基本概念である最少権限を形にしたもので,プロセス単位で各種特権の利用について制限を加えるために用いられます. Linux で対応済みのケイパビリティについては, /usr/include/linux/capability.h の中で参照することができます.しかし, CAP_SYS_ADMIN 権限がさまざまな目的に用いられているので,そのままでは本来の効果が期待できません.そこで TOMOYO Linux では独自にケイパビリティを定義,制御しています(以下「ケイパビリティ」は TOMOYO Linux におけるケイパビリティを指します).
TOMOYO Linux では POSIX とは異なる独自のケイパビリティを使用していますが,プログラムからはその存在は見えないので,プログラムに変更を加える必要はありません.バージョン 1.7.4 では図24の操作の可否を制限することができます.
■図24 TOMOYO Linux 1.7.4 のケイパビリティ
|
ここではマウント操作を行う権限( SYS_MOUNT )を例に説明します. TOMOYO Linux はパス名を用いてアクセス制御を行うため,管理者が期待したとおりにファイルシステムがマウントされていることは絶対の前提となります. root 権限で動作しているすべてのプロセスが好き勝手にマウントをしてしまうようでは困ります.そのため,ケイパビリティを用いることでマウント操作を許可するドメインを制限します.ケイパビリティのアクセス制御の手順はネットワークに関するアクセス制御のときと同様です.まず,制限したいケイパビリティをプロファイルで指定します. /etc/ccs/profile.conf の末尾に図25の内容を追加してください.
■図25 /etc/ccs/profile.conf の末尾に追加する内容(ケイパビリティに対するアクセス制御)
9-CONFIG::capability::SYS_MOUNT={ mode=learning } 10-CONFIG::capability::SYS_MOUNT={ mode=enforcing } |
ファイルやネットワークとは異なり,ケイパビリティの場合は操作対象を指定する必要がありません.学習モードで学習させるだけで強制モードで必要なすべてのケイパビリティが与えられるので,図25のプロファイルでは確認モードを省略しています.保存したら,図3のコマンドを実行して変更を反映してください.
説明のために,先に強制モード用のプロファイルを使用します(図26).
■図26 強制モード用プロファイルを使用
# xargs -0 /usr/sbin/ccs-setprofile -r 10 < /proc/ccs/self_domain |
その後,適当なディレクトリに tmpfs をマウントします(図27).
■図27 tmpfs をマウントする
# mount -t tmpfs none /tmp/ mount: permission denied |
拒否されました.これは, mount コマンドを実行したドメインに対して,マウント操作を行う権限が与えられていないためです.次に,学習モード用のプロファイルを割り当てます(図28).
■図28 学習モード用プロファイルを使用
# xargs -0 /usr/sbin/ccs-setprofile -r 9 < /proc/ccs/self_domain |
再度,適当なディレクトリに tmpfs をマウントします(図29).
■図29 tmpfs をマウントする
# mount -t tmpfs none /tmp/ |
今度は正常に動作しました.ポリシーエディタを起動して mount コマンドを実行したドメインを探し,アクセス許可を確認してください(図30).
■図30 allow_capability SYS_MOUNT というアクセス許可が学習されている |
allow_capability SYS_MOUNT というアクセス許可が学習されていることを確認できます.この状態で強制モード用のプロファイルを割り当てれば,許可されていないドメインからマウント操作を行うことを禁止できるようになります.
マウント操作の可否だけを制限しても,マウント操作が許可されていれば任意のディレクトリにマウントできてしまうので,不十分だと思われる方がいるかもしれません.実際そのとおりであり, TOMOYO Linux ではマウントを許可するパーティションとマウントポイントの組み合わせを制限する機能も備えています.ファイルに対するアクセス制御も学習モードに設定して図29の操作を行うと,図30には allow_mount none /tmp/ tmpfs 0 という結果が学習されるはずです.
TOMOYO Linux では,シグナルの種類と送信先を制限することができます.手順はネットワークに関するアクセス制御のときと同様です. /etc/ccs/profile.conf 末尾に図31の内容を追加してください.
■図31 /etc/ccs/profile.conf の末尾に追加する内容(シグナルに対するアクセス制御)
11-CONFIG::ipc::signal={ mode=learning } 12-CONFIG::ipc::signal={ mode=enforcing } |
保存したら,図3のコマンドを実行して変更を反映してください.
以降の操作は,「 <kernel> /usr/sbin/sshd /bin/bash 」ドメインに属しているシェル(つまり /usr/sbin/sshd からログインしたときのログインシェル)から行うものとします.事前に「 keep_domain <kernel> /usr/sbin/sshd /bin/bash 」という指定がされていないことを確認しておいてください.最初に, /bin/sleep コマンドを実行してください(図32).
■図32 /bin/sleep コマンドを実行
# sleep 100 |
この状態で,別の画面を開いてログインしてください.説明のために,先に強制モード用のプロファイルを割り当てます(図33).
■図33 強制モード用プロファイルを使用
# xargs -0 /usr/sbin/ccs-setprofile -r 12 < /proc/ccs/self_domain |
次に,動作中の /bin/sleep コマンドのプロセスIDを取得し,そのプロセスIDに対してシグナルを送信します(図34.シェルのビルトインではなく, /bin/kill が実行されるよう明示的に指定しています).
■図34 /bin/sleep コマンドのプロセスIDに対してシグナル送信
# pidof sleep 4649 # /bin/kill -15 4649 kill 4649: Operation not permitted |
拒否されました.これは, /bin/kill コマンドが動作するドメインに対して, /bin/sleep コマンドが動作するドメインへシグナルを送信する権限が与えられていないためです.次に,学習モード用のプロファイルを割り当て(図35),再度シグナルを送信します(図36).
■図35 学習モード用プロファイルを使用
# xargs -0 /usr/sbin/ccs-setprofile -r 11 < /proc/ccs/self_domain |
■図36 再度 /bin/sleep コマンドのプロセスIDに対してシグナル送信
# /bin/kill -15 4649 |
今度は正常に動作しました.ポリシーエディタを起動して kill コマンドを実行したドメインを探し,アクセス許可を確認してください(図37).
■図37 kill コマンドを実行したドメインのアクセス許可 |
「 allow_signal 15 <kernel> /usr/sbin/sshd /bin/bash /bin/sleep 」というアクセス許可が学習されていることを確認できます.これは,「 <kernel> /usr/sbin/sshd /bin/bash /bin/sleep 」という名前で始まるドメインに属しているプロセスに対して15番のシグナル( SIGTERM )を送信することを許可するという意味です. TOMOYO Linux におけるドメイン名は <kernel> で始まる階層構造であるため, allow_signal 15 <kernel> のように指定した場合,すべてのプロセスに対して15番のシグナルを送信することが許可されることに注意してください.例外として,シグナルの送信元が送信先と同じドメインの場合はつねに許可されます.また,0番のシグナルもつねに許可されます.
今回は TOMOYO Linux のネットワークのアクセス制御機能を中心に紹介しました.通信を行うドメインを限定したうえで,強力かつ柔軟なアクセス制御を行えることがご理解いただけたと思います.次回は,ログインセッションを制限する方法についての紹介を行います.どうぞお楽しみに.