iptables、ipchains、ipfw プログラミングインタフェースの歴史

iptables、ipchains、ipfw プログラミングインタフェースの歴史

最近、私はGoのルールに触れることにiptables気づきました。桟橋労働者そしてコアラッパーライブラリはコマンドexec()として出力iptablesし、画面は標準出力を取得します。私はこれが私を驚かせた。

Pythonの世界ではPython iptables:

iptablesバイナリを呼び出して出力を解析する代わりに、iptables Cライブラリ(libiptc、libxtables、iptables拡張)を使用してiptablesとの相互運用性を実現します。

私の考えでは、PythonライブラリがCライブラリを実行時にロードできるようにするようですが、Goは[編集:私は間違っています]。しかし、Goはこれらのライブラリに静的にリンクできませんか? Goライブラリはlibxtables.aどこかから得るべきであるのでか。 (Debianで関連パッケージを探していますが、dpkg -Lsだけです。)-dev.so

とにかく、Webフィルタのよくある質問:

4.5ルールを追加/削除するためのC / C ++ APIはありますか?

残念ながら、答えは「いいえ」です。

今、「しかしlibiptcはどうですか?」と思うかもしれません。メーリングリストで何度も指摘したように、libiptcはいいえパブリックインターフェイスとして使用するためのものです。私たちは信頼性の高いインターフェイスを保証せず、次のバージョンのLinuxパケットからそれらを削除する予定です。

我々はこれらのAPIに根本的な欠陥があることに精通しており、状況を改善するために一生懸命努力しています。それまでは、system()を使用するか、iptables-restoreの標準入力でパイプを開くことをお勧めします。後者はより良いパフォーマンスフィルタリングを提供します。 libiptcは合理的に使用するには低すぎるレベルです。

まあ、おそらくこれらのCライブラリを安定しているとは思わないでしょう。それから「自分で話すのはどうですか?」と思いました。ほとんどの場合、カーネルとの会話には使用されず(単にテーブル名を読み取るために?)、メインインタフェースは実際にはバインドされていないソケットにある/procことがわかりました。iptables/procgetsockopt()setsockopt()

これはもう一つの驚きです! (しかし、おそらく私はこの種のコードに慣れていないので、カーネルと対話する興味深い方法のようです。)

iptables私はからまでipchains考古学をして、ipfw次のことを見つけました。1997年のipfwのマニュアルページこれで気分が良くなります。

BUGS
       The  setsockopt(2)  interface  is a crock.  This should be
       put under /proc/sys/net/ipv4 and the world would be a bet-
       ter place.

他の場所では、「ipfwユーティリティはFreeBSD 2.0に初めて提供されます」を見つけることができます。

HISTORY
      Initially this utility was written for BSDI by:
       Daniel Boulet    <[email protected]>
      The FreeBSD version is written completely by:
       Ugen J.S.Antsilevich <[email protected]>
      while synopsis partially compatible with old one.

ipfwこれは1994年のFreeBSD 2.0バージョンです。。まだ使用されていますが、代わりにsetsockopt()使用されているようです。kvm_read()getsockopt()

私の質問

  • 上記の内容が間違っている場合は訂正してください:)
  • {get,set}sockopt()なぜ彼らは最初にそれを選んだのですか?これは珍しいものですか、それとも私にとって新しいものですか?
  • なぜどの時点で変わらなかったのですか?/proc1997のマニュアルページで提案されているのと同じです。
  • なぜ彼らは信頼性の高い/パブリックCインタフェースを思い出せなかったのですかiptables

私のフォローアップの質問

「正確ではありません。デフォルトのインターフェイスは、netlinkのNETLINK_NETFILTERファミリです。」

このヒントを提供していただきありがとうございます!

私が見ています。https://git.netfilter.org/iptables/treeそして、libipq何か欠けていない場合は、netlinkソケットだけが使用されているようです。

$ ick "socket\("
include/libiptc/libiptc.h
158:int iptc_get_raw_socket(void);

include/libiptc/libip6tc.h
152:int ip6tc_get_raw_socket(void);

utils/nfsynproxy.c
129:    fd = socket(AF_INET, SOCK_STREAM, 0);

libiptc/libiptc.c
1312:   sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW);

extensions/libxt_set.h
14: int res, sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);

libipq/libipq.c
223:                h->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_FIREWALL);
225:                h->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_IP6_FW);

libxtables/xtables.c
881:    sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW);

このlibipq内容は私にとって「正常」と思われます。ソケットを作成し、sockaddrなどでsendto()バインドします。recvfrom()

ネットワークリンク操作を実行するために使用されるラッパーxtables-monitorもあるようです。mnl_socket_*

しかし、私はそれを理解することはできませんlibiptcxtablesnetlinkへの言及はなく、ソケットをバインドすることもありません。

https://git.netfilter.org/iptables/tree/libxtables/xtables.c#n881

https://git.netfilter.org/iptables/tree/libiptc/libiptc.c#n1312

mozilla rrデバッガの次のコードのように、netlinkを使用しない(見えますか?)他の例もあります。https://github.com/mozilla/rr/blob/master/src/test/netfilter.c

2000年(2.2)現在、netlinkは{get,set}sockopt()(少なくとも)ipfw古いBSD領域であるLinuxでのみ利用可能です。

bind()もはや私の問題が何であるかよくわかりません:) netlinkではなくソケットがどのようにsockaddrなしで正しいカーネル側と通信するのですか?

ベストアンサー1

私の考えでは、Pythonライブラリは実行時にCライブラリをロードできますが、Goはそうではありません。

行くできる共有Cライブラリを使用してください。

iptablesほとんどの場合、カーネルとの通信には使用されず(/procテーブル名のみを読みますか?)、デフォルトのインタフェースは実際にはgetsockopt()ですsetsockopt()

{get,set}sockopt()なぜ彼らは最初にそれを選んだのですか?これは珍しいものですか、それとも私にとって新しいものですか?

(この回答は、以前はデフォルトのインターフェイスが次のようになっていると誤って指定しました。netlink家族NETLINK_NETFILTER。 )

あなたは正しいです。適切なタイプのバインドされていないソケットへの呼び出しをiptables使用してgetsockoptカーネルと対話し、最終的にカーネルnetfilterコード。私はこれが歴史的な理由だと思います...

ただし、バインド解除を含むさまざまな状態のソケットで作業getsockoptし、setsockopt接続する前にオプションを設定するために使用されるため、これを行う必要があります。 -via-netfilter接続はsockopt実際にはサブチャネルです。

なぜどの時点で変わらなかったのですか?/proc1997のマニュアルページで提案されているのと同じです。

いくつかの理由があるかもしれませんが、その1つは間違いなく以前のバージョンとの互換性です。 Linuxでは、ユーザースペースのインターフェースが絶対に破損してはいけません。これにより、新しいインターフェイスを提供できますが、既存のインターフェイスはそのまま残り、インターフェイスを改善したり、すでに実行されているプログラムを再構築したりするインセンティブを減らします。

コマンドラインツールを少ない労力で使用でき、より良いインターフェースを提供するためには、より多くの労力が必要な限りiptables変更は困難です。適切に維持されたlibiptcスタイルライブラリも可能でしたが、開発者はiptablesそうする動機があまりありませんでした。

なぜ彼らは信頼性の高い/パブリックCインタフェースを思い出せなかったのですかiptables

なぜなら、彼らは問題を解決しなかったからです。今iptables段階的に廃止nftables、これには、さまざまな抽象化レベルでアクセスを提供する複数のライブラリ(libnftables、、、libnftnl)が含まれています。カーネルとユーザー空間の間で情報を転送するためのソケットベースのインターフェースとして設計されており、libnfnetlink(および)などのツールに最適です。ドキュメントには他の利用可能なスイートがリストされており、これにはかなりのカーネルホスティング機能が含まれています。 。netlinknftablesiptablesnetlinknetlink

あなたは見つけることができますhttps://github.com/vishvananda/netlinkiptablesGoで運転するときに便利です。 (これは多くの作業が必要ですが、最初から始めるよりも優れています。)

おすすめ記事