私のiptablesスクリプトでは、できる限り細かいルールを書く実験を行っています。一部のユーザーはセキュリティを確保し、一部は学習課題として、どのユーザーがどのサービスを使用できるかを制限します。
3.6.2カーネルを実行しているDebian 6.0.6でiptables v1.4.16.2を使用します。
しかし、まだよくわからない問題が発生しました。
これは完璧に機能します。一般的な状態追跡ルールはありません。
##発信ポート81 $ IPTABLES -A OUTPUT -p tcp --dport 81 -m conntrack --ctstate NEW、ESTABLISHED -j ACCEPT $ IPTABLES -A INPUT- p tcp --sport 81 -s $ MYIP -m conntrack --ctstate ESTABLISHED -j ACCEPT
## useraccountの送信ポート80 $ IPTABLES -A OUTPUT --match owner --uid-owner useraccount -p tcp --dport 80 -m conntrack --ctstate NEW、ESTABLISHED- sport 1024:65535 -j ACCEPT $ IPTABLES -A INPUT -p tcp --sport 80 --dport 1024:65535 -d $ MYIP -m conntrack --ctstate ESTABLISHED -j ACCEPT
これにより、アカウント "useraccount"に対してのみポート80が許可されますが、TCPトラフィックに対するこのようなルールには問題があります。
##デフォルトの送信ログ+ブロックルール $ IPTABLES -A OUTPUT -j LOG --log-prefix "BAD OUTGOING" --log-ip-options --log-tcp-options- -log-uid $ IPTABLES -A OUTPUT -j DROP
上記は機能し、ユーザー「useraccount」はファイルを完全に正常に取得できます。システム上の他のユーザーは、ポート80への発信接続を行うことができません。
useraccount @ Host:$ wget http://cachefly.cachefly.net/10mb.test
しかし、上記のwgetは、syslogにx7のドロップされたエントリを残します。
Oct 18 02:00:35 xxxx kernel:BAD OUTGOING 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 = TCP SPT = 37792 DPT = 80 SEQ = 164520678 ACK = 3997126942 WINDOW = 979 RES = 0x00 ACK URGP = 0
UDPトラフィックを使用する同様のルールでは、これらのドロップは発生しません。どのユーザーがDNSリクエストを実行できるかを制限するルールがすでに整っています。
ドロップされた送信ACKパケットは、理解できないルートアカウント(URGP = 0)から送信されているようです。ユーザーアカウントをrootに入れ替えても。
3ウェイハンドシェイクの3番目のステップの後でconntrackが接続の追跡を開始するため、ACKパケットは新しいものとして分類されていると思いますが、なぜドロップされるのですか?
これらの低下は安全に無視できますか?
だから私はしばしばこのようなルールを見ます、それは私にとってはうまくいきます:
$ IPTABLES -A OUTPUT -s $ MYIP -p tcp -m tcp --dport 80 -m state --state NEW、ESTABLISHED -j ACCEPT $ IPTABLES -A INPUT -p tcp- m tcp --sport 80 -d $ MYIP -m state --state ESTABLISHED -j ACCEPT
状態の一致が明らかに廃止されたため、「-m state --state」を「-m conntrack --ctstate」に交換しました。
一般的な状態追跡ルールを設定することはベストプラクティスですか?上記のルールは正しいと見なされていませんか?
発信ユーザー接続を厳密に制御するには、このようなものが良いでしょうか?
$ IPTABLES -A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT $ IPTABLES -A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT $ IPTABLES -A OUTPUT -p tcp --dport 80 -s $ SERVER_IP_TUNNEL -m conntrack --ctstate NEW -m owner --uid-owner useraccount -j ACCEPT $ IPTABLES -A OUTPUT -p tcp --dport 80 -s $ SERVER_IP_TUNNEL -m conntrack --ctstate NEW -m owner --uid-owner otheraccount -j ACCEPT
簡単に言えば、ソケットが誰にも属していないときにそのACKが送信されました。ユーザーx
に属するソケットに関係するパケットを許可する代わりに、ユーザーx
からのソケットによって開始された接続に関係するパケットを許可します。
長い話。
この問題を理解するには、wget
およびHTTPリクエストが一般的にどのように機能するかを理解することが役立ちます。
に
wget http://cachefly.cachefly.net/10mb.test
wget
は、TCPへの接続を確立しますcachefly.cachefly.net
、そして確立されると、次のようなHTTPプロトコルでリクエストを送信します。「/10mb.test
(GET /10mb.test HTTP/1.1
)ちなみに、完了後に接続を閉じないでください(Connection: Keep-alive
)。その理由は、サーバーが同じIPアドレスのURLのリダイレクトで応答した場合、接続を再利用できるためです。
これで、サーバーはどちらかで応答できます。「ここに、要求されたデータが来ます。10MBあることに注意してください(Content-Length: 10485760
)、はいOK、接続を開いたままにします "または、データのサイズがわからない場合は、"データです。接続を開いたままにすることはできませんが、いつ通知しますか接続の終わりを閉じると、データのダウンロードを停止できます。」.
上記のURLでは、最初のケースです。
したがって、wget
が応答のヘッダーを取得するとすぐに、10MBのデータをダウンロードすると、そのジョブが完了したことがわかります。
基本的に、wget
は、10MBが受信されて終了するまでデータを読み取ります。しかし、その時点で、やるべきことはまだあります。サーバーはどうですか?接続を開いたままにするように言われました。
終了する前に、wget
はソケットのファイル記述子を閉じます(close
システムコール)。すると、close
、システムはサーバーから送信されたデータの確認を終了し、FIN
を送信して「これ以上データを送信しません」と伝えます。その時点で、close
が戻り、wget
が終了します。 TCP接続に関連付けられたソケットはもうありません(少なくとも、ユーザーが所有しているソケットはありません)。しかし、まだ完了していません。そのFIN
を受信すると、HTTPサーバーはend -of-fileクライアントから次のリクエストを読み取るとき。HTTPでは、「これ以上のリクエストはありません。終了します」という意味です。そのため、FINも送信します。いずれかを送信すると、その接続はなくなります。」.
そのFINを受信すると、クライアントは「ACK」を送信します。しかし、その時点では、wget
がなくなっているため、ACKはどのユーザーからも送信されません。これがファイアウォールによってブロックされている理由です。サーバーはACKを受信しないので、あきらめるまでFINを繰り返し送信し、ドロップされたACKがさらに表示されます。つまり、これらのACKをドロップすることにより、かなり長い間、サーバーのリソース(ソケットをLAST-ACK状態に維持する必要がある)を不必要に使用することになります。
クライアントが「Keep-alive」を要求しなかった場合、またはサーバーが「Keep-alive」で応答しなかった場合の動作は異なります。
すでに述べたように、接続トラッカーを使用している場合、目的は、ESTABLISHEDおよびRELATED状態のすべてのパケットを通過させ、NEW
パケットのみを考慮することです。
ユーザーNEW
からのx
パケットを許可し、ユーザーy
からのパケットは許可しない場合、ユーザーx
による確立された接続の他のパケットは通過します。ユーザーy
による確立された接続がないため(NEW
接続を確立します)、ユーザーy
接続が通過するパケットはありません。
これにより、アカウント「useraccount」に対してのみポート80が許可されます。
—ええと、少なくともあなたが示したルールは、実際にはこれを意味するものではありません。
アドバイスの余地もあります— ESTABLISHEDストリームではユーザーチェックを行わず、NEWでチェックしてください。 Incoming ESTABLISHEDをチェックするときにソースポートをチェックするポイントもわかりません。どのポートとの違いは何ですか。それはconntrackのPoVからすでにESTABLISHED状態になっています。ファイアウォールは可能な限りシンプルである必要がありますが、効率的であるため、 Occamのかみそり アプローチが最適です。