デール・ハグルンドがスポットです。それで、私は同じことを異なる方法で、いくつかの詳細と例を挙げて言うつもりです。☺
UnixおよびLinuxの世界で正しいことは次のとおりです。
- スーパーユーザーとして実行され、リスニングソケットをバインドする、小さく、シンプルで、監査が容易なプログラムを用意する。
- 最初のプログラムによって生成された、特権をドロップする別の小さく、シンプルで、監査しやすいプログラムを用意する。
- サービスの内容を別の3番目のプログラムで、スーパーユーザー以外のアカウントで実行し、2番目のプログラムによってロードされたチェーンで、ソケットのオープンファイル記述子を単純に継承することを期待します。
リスクが高い場所について間違った考えを持っています。リスクが高いのは、ネットワークから読み取り、ソケットを開いてポートにバインドし、を呼び出すという単純な行為ではない読み取り内容に基づいて行動することですlisten()
。リスクが高いのは、実際の通信を行うサービスの一部です。開く部分、、bind()
およびlisten()
、さらに(ある程度)部分accepts()
は、高リスクではなく、スーパーユーザーの保護下で実行できます。accept()
ネットワーク上の信頼できない見知らぬ人の制御下にあるデータを使用し、(この場合のソースIPアドレスを除いて)データに基づいて行動することはありません。
これを行うには多くの方法があります。
inetd
Dale Hagglundが言うように、古い「ネットワークスーパーサーバー」inetd
がこれを行います。サービスプロセスが実行されるアカウントは、の列の1つですinetd.conf
。リスニング部分とドロップする特権部分を小さくて監査しやすい2つの別個のプログラムに分離しませんが、メインのサービスコードを別個のプログラムに分離exec()
し、オープンファイル記述子で生成されるサービスプロセスで編集しますソケット用。
1つのプログラムを監査するだけでよいので、監査の難しさはそれほど問題ではありません。 inetd
の主な問題は、それほど多くの監査ではなく、最新のツールと比較して、単純なきめ細かいランタイムサービス制御を提供しないことです。
UCSPI-TCPおよびdaemontools
ダニエルJ.バーンスタインのUCSPI-TCPおよびdaemontoolsパッケージは、これを組み合わせて行うように設計されています。あるいは、Bruce Guenterのほぼ同等のdaemontools-encoreツールセットを使用できます。
ソケットファイル記述子を開き、特権ローカルポートにバインドするプログラムはtcpserver
、UCSPI-TCPからです。との両方listen()
を行いaccept()
ます。
tcpserver
次に、ルート特権自体をドロップするサービスプログラムを生成します(サービス対象のプロトコルは、スーパーユーザーとして起動し、たとえばFTPまたはSSHデーモンの場合のように「ログオン」する必要setuidgid
があるため)。自己完結型の小さくて監査が容易なプログラムで、特権を単にドロップし、その後、適切なサービスプログラムにロードをチェーンします(したがって、その一部はスーパーユーザー特権で実行されませんqmail-smtpd
。
run
したがって、サービススクリプトは、たとえば、次のようになります(これは、null IDENTサービスを提供するdummyidentd用です)。
#!/bin/sh -e
exec 2>&1
exec \
tcpserver 0 113 \
setuidgid nobody \
dummyidentd.pl
いや
私のnoshパッケージはこれを行うように設計されています。他のsetuidgid
ユーティリティと同様に、小さなユーティリティがあります。一つのわずかな違いは、それはで使用可能だということですsystemd
スタイルの「LISTEN_FDS」のサービスだけでなく、UCSPI-TCPサービスと、その伝統的なtcpserver
プログラムは、2つの別々のプログラムによって置き換えられますtcp-socket-listen
とtcp-socket-accept
。
繰り返しますが、単一目的のユーティリティが相互に生成され、チェーンがロードされます。設計の1人の興味深い癖は1つが後にスーパーユーザ権限をドロップすることができるということですlisten()
が、前であってもaccept()
。実際run
にqmail-smtpd
それを行うスクリプトは次のとおりです。
#!/bin/nosh
fdmove -c 2 1
clearenv --keep-path --keep-locale
envdir env/
softlimit -m 70000000
tcp-socket-listen --combine4and6 --backlog 2 ::0 smtp
setuidgid qmaild
sh -c 'exec \
tcp-socket-accept -v -l "${LOCAL:-0}" -c "${MAXSMTPD:-1}" \
ucspi-socket-rules-check \
qmail-smtpd \
'
スーパーユーザの庇護の下で実行するプログラムは、小さなサービスに依存しないチェーンローディングツールですfdmove
、clearenv
、envdir
、softlimit
、tcp-socket-listen
、とsetuidgid
。sh
開始された時点で、ソケットは開いてsmtp
ポートにバインドされており、プロセスにはスーパーユーザー特権がありません。
s6、s6-networking、execline
Laurent Bercotのs6およびs6-networkingパッケージは、これを組み合わせて行うように設計されています。コマンドの構造はdaemontools
、UCSPI-TCPと非常によく似ています。
run
s6-tcpserver
for tcpserver
とs6-setuidgid
forの置換を除いて、スクリプトはほとんど同じですsetuidgid
。ただし、M。Bercotのexeclineツールセットを同時に使用することもできます。
以下は、execline、s6、s6-networking、およびpublicfileの FTPサーバープログラムを使用するWayne Marshallの元のから少し変更されたFTPサービスの例です。
#!/command/execlineb -PW
multisubstitute {
define CONLIMIT 41
define FTP_ARCHIVE "/var/public/ftp"
}
fdmove -c 2 1
s6-envuidgid pubftp
s6-softlimit -o25 -d250000
s6-tcpserver -vDRH -l0 -b50 -c ${CONLIMIT} -B '220 Features: a p .' 0 21
ftpd ${FTP_ARCHIVE}
ipsvd
Gerrit Papeのipsvdは、ucspi-tcpおよびs6-networkingと同じラインで実行される別のツールセットです。ツールがあるchpst
とtcpsvd
、この時間が、彼らは同じことを行うと、信頼できないクライアントがネットワークを介して送信されるものの読み取り、処理、および書き込みを行い、高リスクコードは別のプログラムにまだあります。
ここだM.パプの例実行されているのfnord
ではrun
スクリプトは:
#!/bin/sh
exec 2>&1
cd /public/10.0.5.4
exec \
chpst -m300000 -Uwwwuser \
tcpsvd -v 10.0.5.4 443 sslio -v -unobody -//etc/fnord/jail -C./cert.pem \
fnord
systemd
systemd
、一部のLinuxディストリビューションにある新しいサービス監視と初期化システムは、できることを行うことを目的としてinetd
います。ただし、小さな自己完結型プログラムのスイートは使用しません。systemd
残念ながら、全体を監査する必要があります。
systemd
1ソケット定義するための設定ファイルを作成するsystemd
上でリッスンし、サービスsystemd
を開始します。サービスの「ユニット」ファイルには、実行するユーザーなど、サービスプロセスを大幅に制御できる設定があります。
そのユーザーを非スーパーユーザーに設定してsystemd
、ソケットを開き、ポートにバインドし、プロセス#1でスーパーユーザーとして呼び出すlisten()
(および必要に応じてaccept()
)のすべての作業を行い、サービスプロセスspawnsはスーパーユーザー権限なしで実行されます。