Netfilter/iptablesのいくつかの新しい進展
5887 ワード
Netfilterの最新の進展に注目して、新しいものは本当に多いですね.でも一番ドキドキするのは2つ.
一.新しいbpfモジュール
Linux kernel 3.9バージョンベースのpatchはxt_bpfのサポート、対応するiptablesモジュールはlibxt_bpf、これはiptables-1.4.19バージョンでサポートされています.その名の通り、bpfはバークレーパケットフィルタリングの略で、その説明については『BPF(BSD Packet Filter)--応用と理念の拡張』を参照してください.名称上、BPFはiptablesパッケージフィルタリングの第一選択技術であるはずだが、なぜかxt_tablesは常に独自のデータ構造を維持してruleのmatchとtargetを保存しており、現在BPFのサポートがあり、カーネルプロトコルスタックはiptablesルールを処理する際の効率が高くなると思います.従来の一連の複数のmatchは、bytecodeパラメータで示すことができ、コンパイルされたバイトコードであり、カーネルが直接実行するmatchにカプセル化されています.スピードが非常に速い.従来のmatchマッチングは基本的に遍歴であり、現在はbpfベースの遍歴ではなく、bytecodeを「実行」する!tcpdumpツールは従来BPFベースであるが、そのmatchは文法的にiptablesと極めて類似しているが、その整合効率はiptalesよりずっと高く、-i eth 2 tcp port 1234 and host 1.2.3.4のような整合はiptablesで4つのentryを確立する必要があるが、BPFを使用すると、以下の順序で実行するコードにコンパイルすることができる:1.devフィールド2をロードする.devフィールドを判断し、eth 2でない場合はx 3にジャンプする.プロトコルフィールド4をロードする.プロトコルフィールドを判断し、tcpでなければx...x.このコードはアセンブリコードに類似して返され、カーネル解釈によって実行される.しかし、私はkernel 2.6.32でコンパイルに成功しませんでした.このバージョンは古いので、多くのインタフェースと新しいカーネルが互換性がなく、長い間変更してやっとやっと実行できましたが、複雑なbytecodeを挿入することはできません.そうしないとpanicになります.いずれにしても、このBPFのアーキテクチャを採用すると、カーネル空間のコード実行効率が大幅に向上し、ipt_のようなコード量も大幅に減少します.do_tableというビッグマック関数も痩せるようになりました.
二.最新のnftablesプロジェクト
iptablesカーネルコードのダイエットといえば、Netfilterのウェブサイトには、既存のiptables/ebtables/arptablesおよび対応するv 6バージョンを完全に置き換えるためのnftablesプロジェクトという別の道が開かれています.nftablesの最も主要な革新は2つの点にあり、1つはコマンド構文の完全な変更であり、2つ目はカーネルコードの最適化である.BPFのようなフィルタリング方式を採用しており、matchesのマッチングプロセスはステータスマシン変換のプロセスであり、最終的な終了ノードはtargetである.コードレベルでは、matchストレージに対するiptablesの混乱した場面を完全に変更しました.以下は、一致するコアコードです.
新しいnftablesダイエットの原因は、コールバック関数を大量に採用し、判定ロジックを独立させ、コアのdo_tablesは単純なステータスマシンになりました!この抽出動作がもたらす効果はruleがより柔軟になったことであり,BPFの考え方のようにパケットは一歩一歩の結果に応じて異なるruleまたは異なるmatchの間で任意にジャンプすることができる.iptablesのマッチング過程での大量の判断に比べて、結果はハードコーディングで、nftablesは確かに質的な飛躍があり、nftablesが早く発表されることを期待しています.
一.新しいbpfモジュール
Linux kernel 3.9バージョンベースのpatchはxt_bpfのサポート、対応するiptablesモジュールはlibxt_bpf、これはiptables-1.4.19バージョンでサポートされています.その名の通り、bpfはバークレーパケットフィルタリングの略で、その説明については『BPF(BSD Packet Filter)--応用と理念の拡張』を参照してください.名称上、BPFはiptablesパッケージフィルタリングの第一選択技術であるはずだが、なぜかxt_tablesは常に独自のデータ構造を維持してruleのmatchとtargetを保存しており、現在BPFのサポートがあり、カーネルプロトコルスタックはiptablesルールを処理する際の効率が高くなると思います.従来の一連の複数のmatchは、bytecodeパラメータで示すことができ、コンパイルされたバイトコードであり、カーネルが直接実行するmatchにカプセル化されています.スピードが非常に速い.従来のmatchマッチングは基本的に遍歴であり、現在はbpfベースの遍歴ではなく、bytecodeを「実行」する!tcpdumpツールは従来BPFベースであるが、そのmatchは文法的にiptablesと極めて類似しているが、その整合効率はiptalesよりずっと高く、-i eth 2 tcp port 1234 and host 1.2.3.4のような整合はiptablesで4つのentryを確立する必要があるが、BPFを使用すると、以下の順序で実行するコードにコンパイルすることができる:1.devフィールド2をロードする.devフィールドを判断し、eth 2でない場合はx 3にジャンプする.プロトコルフィールド4をロードする.プロトコルフィールドを判断し、tcpでなければx...x.このコードはアセンブリコードに類似して返され、カーネル解釈によって実行される.しかし、私はkernel 2.6.32でコンパイルに成功しませんでした.このバージョンは古いので、多くのインタフェースと新しいカーネルが互換性がなく、長い間変更してやっとやっと実行できましたが、複雑なbytecodeを挿入することはできません.そうしないとpanicになります.いずれにしても、このBPFのアーキテクチャを採用すると、カーネル空間のコード実行効率が大幅に向上し、ipt_のようなコード量も大幅に減少します.do_tableというビッグマック関数も痩せるようになりました.
二.最新のnftablesプロジェクト
iptablesカーネルコードのダイエットといえば、Netfilterのウェブサイトには、既存のiptables/ebtables/arptablesおよび対応するv 6バージョンを完全に置き換えるためのnftablesプロジェクトという別の道が開かれています.nftablesの最も主要な革新は2つの点にあり、1つはコマンド構文の完全な変更であり、2つ目はカーネルコードの最適化である.BPFのようなフィルタリング方式を採用しており、matchesのマッチングプロセスはステータスマシン変換のプロセスであり、最終的な終了ノードはtargetである.コードレベルでは、matchストレージに対するiptablesの混乱した場面を完全に変更しました.以下は、一致するコアコードです.
// , iptables
struct nft_expr {
const struct nft_expr_ops *ops;
unsigned char data[];
};
struct nft_rule {
struct list_head list;
struct list_head dirty_list;
struct rcu_head rcu_head;
u64 handle:46,
genmask:2,
dlen:16;
unsigned char data[]
__attribute__((aligned(__alignof__(struct nft_expr))));
};
//net/netfilter/nf_tables_core.c
unsigned int
nft_do_chain_pktinfo(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
{
const struct nft_chain *chain = ops->priv;
const struct nft_rule *rule;
const struct nft_expr *expr, *last;
struct nft_data data[NFT_REG_MAX + 1];
unsigned int stackptr = 0;
struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE];
int rulenum = 0;
/*
* Cache cursor to avoid problems in case that the cursor is updated
* while traversing the ruleset.
*/
unsigned int gencursor = chain->net->nft.gencursor;
do_chain:
rule = list_entry(&chain->rules, struct nft_rule, list);
next_rule:
data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
list_for_each_entry_continue_rcu(rule, &chain->rules, list) {
/* This rule is not active, skip. */
if (unlikely(rule->genmask & (1 << gencursor)))
continue;
rulenum++;
nft_rule_for_each_expr(expr, last, rule) {
if (expr->ops == &nft_cmp_fast_ops)
nft_cmp_fast_eval(expr, data);
else if (expr->ops != &nft_payload_fast_ops ||
!nft_payload_fast_eval(expr, data, pkt))
expr->ops->eval(expr, data, pkt);
if (data[NFT_REG_VERDICT].verdict != NFT_CONTINUE)
break;
}
switch (data[NFT_REG_VERDICT].verdict) {
case NFT_BREAK:
data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
/* fall through */
case NFT_CONTINUE:
continue;
}
break;
}
switch (data[NFT_REG_VERDICT].verdict) {
//
case NF_ACCEPT:
case NF_DROP:
case NF_QUEUE:
nft_chain_stats(chain, pkt, jumpstack, stackptr);
if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
return data[NFT_REG_VERDICT].verdict;
case NFT_JUMP:
//stack rule
if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
BUG_ON(stackptr >= NFT_JUMP_STACK_SIZE);
jumpstack[stackptr].chain = chain;
jumpstack[stackptr].rule = rule;
jumpstack[stackptr].rulenum = rulenum;
stackptr++;
/* fall through */
case NFT_GOTO:
chain = data[NFT_REG_VERDICT].chain;
goto do_chain;
case NFT_RETURN:
if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RETURN);
/* fall through */
case NFT_CONTINUE:
break;
default:
WARN_ON(1);
}
if (stackptr > 0) {
if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_RETURN);
stackptr--;
chain = jumpstack[stackptr].chain;
rule = jumpstack[stackptr].rule;
rulenum = jumpstack[stackptr].rulenum;
goto next_rule;
}
nft_chain_stats(chain, pkt, jumpstack, stackptr);
if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_POLICY);
return nft_base_chain(chain)->policy;
}
新しいnftablesダイエットの原因は、コールバック関数を大量に採用し、判定ロジックを独立させ、コアのdo_tablesは単純なステータスマシンになりました!この抽出動作がもたらす効果はruleがより柔軟になったことであり,BPFの考え方のようにパケットは一歩一歩の結果に応じて異なるruleまたは異なるmatchの間で任意にジャンプすることができる.iptablesのマッチング過程での大量の判断に比べて、結果はハードコーディングで、nftablesは確かに質的な飛躍があり、nftablesが早く発表されることを期待しています.