web-dev-qa-db-ja.com

Nftablesタイムスタンプマップ

タイムスタンプに基づいてnftablesマップを作成することは可能ですか?

現在私が使用しているもの:

numgen random mod 2 map {
            0: 10.10.10.1,
            1: 10.10.10.2,
        }

しかし、random mod 2式を(timestamp / 1800) mod 2に変換する方法、つまり、01のようなマップのキーを30分ごとに交互に生成する方法はありますか?

1
mvorisek

map という名前の事前に計算されたルックアップを使用することで、nftablesの制限を回避することができます。

必須:

  • カーネル> = 5.4:meta hourの場合
  • nftables> = 0.9.4 typeofの代わりに使用できる新しいtypeの場合、これはmeta hourmapでサポートされている唯一の構文のようです。 type meta hourが古いnftablesでtype hourとして読み戻された場合でも、typeof meta hourまたはtype hourは受け入れられません。

nftablesは、任意の算術(または論理など)演算を実行できません。現在、パケットパスまたはnumgenのようないくつかの拡張子から取得する必要があるデータに対して、左側(LHS)でいくつかの操作を実行し、それを一定の右側(RHS)と比較することに制限されています。セットとマップからRHS値を取得することを含みます。

nftables LHSで任意の除算を計算する方法はありません(右シフトを使用して2の累乗で除算しますが、後で参照してください)。また、名前付きマップでキーとして受け入れられるデータ型などの計算結果を表現する方法もないようです。これは、「非修飾」integer型がそのような操作の結果であることが多いためです。少なくとも現在のところ、名前付きマップでは有効なキータイプではありません。たとえば、匿名マップで機能する場合でも、numgen式をnamedマップで使用できるかどうかはわかりません。

この場合、 Linuxカーネル5.4 は、カーネル内のパケットのタイムスタンプに関連するメタステートメントを導入します。

  • 時間、日、時間のメタ一致をカーネルに導入します commit

ここで、meta hourは、不足している必須操作「mod 86400」を提供します。これは、OPの「タイムスタンプ/ 1800」の要件に十分に関連しています。1日の始まりからのパケットの時刻を示します。さらに、特定のタイプがあり、名前付きマップで使用できます。

loop unrolling と同様の方法として、複雑な操作を簡略化するため、式で計算できない値は、型が名前付きで有効である限り、事前に計算してマップテーブルに格納できます。地図。エントリの数は事前にわかっていて、まだ制限されているため、これは許容されます。この場合、1日は48時間半です。

マッピングにより、最終結果であるIPv4アドレスを提供できます。


wanで受信したすべてのトラフィックを各時間の最初の30分で10.10.10.1に転送し、後半の10.10.10.2に転送するロードバランサーのルールセットの例(実行dnat) :

table ip mytable
delete table ip mytable

table ip mytable {
        map hour2ip {
                typeof meta hour : ip daddr
                flags interval
        }
        chain mylb {
                type nat hook prerouting priority dstnat; policy accept;
                iif wan0 dnat to meta hour map @hour2ip
        }
}

マップにデータを入力するためのnftablesコマンドを生成するスクリプトhour2ip./script.sh | nft -f -を使用):

#!/bin/sh

for h in $(seq 0 23); do
        for m in 0 30; do
        printf 'add element ip mytable hour2ip { "%02d:%02d:00"-"%02d:%02d:59" : %s }\n' $h $m $h $((m+29)) '$ip'
        done
done |
        sed 's/$ip/10.10.10.X/g' |
        awk '{ printf "%s\n",gensub("X",(NR-1)%2+1,1) }'

この種のコマンドを生成します:

add element ip mytable hour2ip { "00:00:00"-"00:29:59" : 10.10.10.1 }
add element ip mytable hour2ip { "00:30:00"-"00:59:59" : 10.10.10.2 }
[...]
add element ip mytable hour2ip { "23:00:00"-"23:29:59" : 10.10.10.1 }
add element ip mytable hour2ip { "23:30:00"-"23:59:59" : 10.10.10.2 }

ノート:

  • ローカルタイムゾーンは、タイプmeta hour(モジュロ)のデータが、通常はUTC時間を使用しているカーネルとの間で送受信される方法に影響を与えます。そのため、現在のタイムゾーンに応じて順序がずれて表示されますが、期待どおりに動作します。 TZ=UTCを表示するときに、環境変数nft list map ip mytable hour2ipを使用するかどうかの効果を確認して、理解を深めることができます。
  • 00:29:59と00:30:00の間にギャップはありません。タイムスタンプは切り捨てられるため、たとえば00:29:59.800msは00:29:59と一致します。

markを使用して柔軟性を高める場合(dnatルール以外の場所でmarkを再利用することにより、-に保存することを含む) connmark)、たとえば2つのマップを使用できます。1つはマップにhourからmarkに、もう1つはマップにmark IPアドレスに。

これを行うには、たとえば前のルールセットを次のように置き換えます。

table ip mytable
delete table ip mytable

table ip mytable {
        map hour2mark {
                typeof meta hour : meta mark
                flags interval
        }

        map mark2ip {
                typeof meta mark : ip daddr
                elements = { 1 : 10.10.10.1, 2 : 10.10.10.2 }
        }

        chain mylb {
                type nat hook prerouting priority dstnat; policy accept;
                iif wan0 meta mark set meta hour map @hour2mark  dnat to meta mark map @mark2ip
        }
}

エントリを生成する前のスクリプトで置き換えます。

        sed 's/$ip/10.10.10.X/g' |

と:

        sed 's/hour2ip/hour2mark/;s/$ip/X/g' |

入力するコマンドを作成するにはhour2mark、次のようになります。

add element ip mytable hour2mark { "00:00:00"-"00:29:59" : 1 }
add element ip mytable hour2mark { "00:30:00"-"00:59:59" : 2 }
[...]
add element ip mytable hour2mark { "23:00:00"-"23:29:59" : 1 }
add element ip mytable hour2mark { "23:30:00"-"23:59:59" : 2 }
1
A.B