Iptables:発信トラフィックをconntrackと所有者と一致させます。奇妙な水滴で動作

Iptables:発信トラフィックをconntrackと所有者と一致させます。奇妙な水滴で動作

私のiptablesスクリプトでは、私はできるだけ細かいルールを書こうとしました。部分的にはセキュリティのために、部分的には学習練習でどのユーザーがどのサービスを使用できるかを制限します。

3.6.2 カーネルを実行する Debian 6.0.6 で iptables v1.4.16.2 を使用します。

ところがとても理解できない問題に封着しました…

すべてのユーザーのための発信ポート

これは非常にうまく機能します。一般的な状態追跡ルールはありません。

##発信ポート81
$IPTABLES -A 出力 -p tcp --dport 81 -m conntrack --ctstate 新規、設定済み -j 受け入れ
$IPTABLES -A 入力 -p tcp --sport 81 -s $MYIP -m conntrack --ctstate 設立 -j 承諾

発信ポート一致ユーザー

## ユーザーアカウントの発信ポート 80
$IPTABLES -A 出力 --match owner --uid-owner useraccount -p tcp --dport 80 -m conntrack --ctstate 新規、確立済み --sport 1024:65535 -j accept
$IPTABLES -A 入力 -p tcp --sport 80 --dport 1024:65535 -d $MYIP -m conntrack --ctstate 設立 -j 承諾

これにより、「useraccount」アカウントのみがポート80を使用できますが、TCPトラフィックに関するこれらの規則には問題があります。

##デフォルトの発信ログ+ブロックルール
$IPTABLES -A 出力 -j log --log-prefix "BAD OUTGOING" --log-ip-options --log-tcp-options --log-uid
$IPTABLES -A 出力 -j 削除

質問

上記の操作が機能し、ユーザー「useraccount」がファイルを完全にインポートできます。システムの他のユーザーはポート 80 への接続を確立できません。

useraccount@host:$ wget http://cachefly.cachefly.net/10mb.test

しかし、上記のwgetは私のシステムログにx7削除されたエントリを残しました。

Oct 18 02:00:35 xxxx カーネル: 発信エラー IN= OUT=eth0 SRC=xx.xx.xx.xx DST=205.234.175.175 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=12170 DF PROTO SPT=37792 DPT=80 SEQ=164520678 ACK=3997126942 WINDOW=979 RES=0x00 ACK URGP=0  

UDP トラフィックに対する同様のルールについては、これらの削除メッセージは表示されません。 DNSリクエストを実行できる人を制限するルールを設定しました。

削除された発信ACKパケットはルートアカウント(URGP = 0)から来ているようですが、理解できません。ユーザーアカウントをrootに変更しても。

conntrackは3ウェイハンドシェークのステップ3以降に接続追跡を開始するため、ACKパケットが新しいパケットに分類されると考えていますが、なぜ削除されますか?

これらの滴を無視しても安全ですか?

編集する

だから私はしばしば私によく合う次の規則を見ます。

$IPTABLES -A 出力 -s $MYIP -p tcp -m tcp --dport 80 -m 状態 --新規、確立済み -j 受け入れ
$IPTABLES -A 入力 -p tcp -m tcp --sport 80 -d $MYIP -m ステータス --ステータス設定 -j 受け入れ

状態マッチングが使用されなくなったため、「-m state --state」を「-m conntrack --ctstate」に置き換えました。

普遍的な状態追跡ルールを持つのがベストプラクティスですか?上記のルールは正しいと見なされませんか?

発信ユーザー接続を厳密に制御するには、このような方が良いでしょうか?

$IPTABLES -A 入力 -m conntrack --ctstate 設定済み -j 受け入れ
$IPTABLES -A 出力 -m conntrack --ctstate 設定済み -j 受け入れ

$IPTABLES -A 出力 -p tcp --dport 80 -s $SERVER_IP_TUNNEL -m conntrack --ctstate NEW -m owner --uid-owner useraccount -j ACCEPT

$IPTABLES -A 出力 -p tcp --dport 80 -s $SERVER_IP_TUNNEL -m conntrack --ctstate NEW -m owner --uid-owner otheraccount -j ACCEPT

ベストアンサー1

簡単に言えば、ソケットが誰にも属していないときにACKが送信されます。xユーザーのソケットに属するパケットを許可するのではなく、ユーザーのソケットによって開始された接続に属するパケットを許可しますx

物語が比較的長いです。

この問題を理解するには、wgetHTTP要求が通常どのように機能するかを理解するのが役立ちます。

存在する

wget http://cachefly.cachefly.net/10mb.test

wgetcachefly.cachefly.netTCP接続が確立されたら、「()の内容を送信してください。ただし、完了したら接続()を閉じないでください」という内容の要求がHTTPプロトコルに送信されます。これは、サーバーが同じIPアドレスからURLリダイレクトに応答したときに接続を再利用できるためです。/10mb.testGET /10mb.test HTTP/1.1Connection: Keep-alive

これで、サーバーは「要求されたデータがここにあります。10 MBのサイズです(Content-Length: 10485760)。はい、わかりました。接続を維持します」と回答できます。または、データのサイズがわからない場合は、「ここにデータがあります。申し訳ありません。接続を開いたままにすることはできませんが、接続の終わりを閉じてデータのダウンロードを停止できるタイミングをお知らせします。」

上記のURLでは、最初の状況にあります。

したがって、wget応答ヘッダーを取得すると、10 MB のデータがダウンロードされたら、操作が完了したことがわかります。

デフォルトでは、wget10 MBを受信するまでデータを読み取って終了します。しかし、それまではやるべきことがもっと残っています。サーバーはどうですか?接続を開いたままにするように指示されました。

終了する前にソケットのファイル記述子をwget閉じます(システムコール)。closeこの時点で、closeシステムはサーバーから送信されたデータの承認を完了し、FIN「これ以上データを送信しません」というメッセージを送信します。その後、close戻ってwget終了します。これ以上TCP接続に関連付けられているソケットはありません(少なくともユーザーは所有していません)。しかし、まだ終わっていません。このメッセージを受信した後、FINHTTPサーバーはファイルの終わりクライアントから次の要求を読み取るとき。 HTTPでは、これは「もう要求がありません。完了しました」を意味します。だから「私も何も送らずに接続が切れています」というFINも送ります。

FINを受信した後、クライアントは「ACK」を送信します。しかし、当時はwgetすでに消えてからずっと長いので、ACKはどのユーザーからも送信されませんでした。だからファイアウォールで詰まっています。サーバーはACKを受信しないため、放棄し、さらにACKが削除されるまでFINを送信し続けます。これはまた、これらのACKを削除すると、かなりの期間にサーバーリソースを不必要に使用することを意味します(ソケットをLAST-ACK状態に保つ必要があります)。

クライアントが「キープアライブ」を要求しない場合、またはサーバーが「キープアライブ」で応答しない場合、動作は異なります。

すでに述べたように、接続トラッカーを使用している場合は、すべてのパケットがESTABLISHED状態とRELATED状態に合格し、パケットについて心配する必要がありますNEW

NEWuserのパケットは許可しますxが、userのパケットは許可しない場合、ユーザーが確立した接続の他yのパケットはx通過し、ユーザーは接続を確立できないため(接続を確立するパケットをブロックしたyため)、すべてのユーザー接続パケットは通過しません。ではありません。 。NEWy

おすすめ記事