Назад | Перейти на главную страницу

Карта временных меток Nftables

Можно ли построить карту nftables на основе метки времени?

В настоящее время использую:

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

Но как преобразовать random mod 2 выражение для (timestamp / 1800) mod 2, т.е. для создания ключей для карты вроде 0 и 1 чередуя каждые 30 минут?

Можно обойти столы ограничения с использованием предварительно вычисленного поиска с именем карта.

Необходимые:

  • ядро> = 5.4: для meta hour
  • nftables> = 0.9.4 для новее typeof который можно использовать вместо type и который, по-видимому, является единственным синтаксисом, поддерживаемым в карта для meta hour. type meta hour или type hour не будет принято, даже если typeof meta hour читается как type hour с более старой версией nftables.

nftables не может выполнять произвольные арифметические (логические и т. д.) операции. В настоящее время он ограничен выполнением нескольких операций в левой части (LHS) с данными, которые должны поступать из пути пакета или несколькими расширениями, такими как numgenи сравните его с постоянной правой частью (RHS), включая получение значения RHS из наборов и карт.

Нет возможности иметь столы вычислить произвольное деление в LHS (используя сдвиг вправо для деления на степень двух, работает, но см. позже). И, похоже, также нет способа выразить результат такого вычисления как тип данных, принятый в качестве ключа в именованной карте, потому что "неквалифицированный" целое число Тип, который часто является результатом таких операций, не является допустимым типом ключа в именованной карте, по крайней мере, в настоящее время. Например, я не уверен numgen выражение может использоваться с названный map, даже если он работает с анонимной картой.

В этом случае Ядро Linux 5.4 вводит мета-операторы, связанные с отметкой времени пакета в ядре:

  • Ввести мета-совпадения в ядро ​​для времени, дня и часа совершить

Вот, meta hour обеспечивает отсутствующую требуемую операцию "mod 86400", которая достаточно связана с требованием OP "timestamp / 1800": дает время пакета с начала дня. Более того, он имеет определенный тип, что позволяет использовать его в именованной карте.

Как метод, аналогичный разворачивание петли для упрощения сложных операций значения, которые нельзя вычислить в выражениях, можно предварительно вычислить и сохранить в таблице карты, если тип допустим для именованной карты. Это приемлемо, потому что количество записей будет известно заранее и все еще ограничено: в этом случае в сутках 48 полчасов.

После этого сопоставление может дать окончательный результат: адрес IPv4.


Пример набора правил для балансировщика нагрузки (выполнение dnat), который перенаправляет весь трафик, полученный на wan0 до 10.10.10.1 первые полчаса каждого часа и до 10.10.10.2 вторые полчаса:

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,800 мс по-прежнему соответствует 00:29:59.

Если вы предпочитаете использовать отметка для большей гибкости (повторное использование отметка в другом месте, кроме dnat правило, включая сохранение его в Connmark), вы можете использовать, например, две карты: одну для отображения час к отметка и другой на карту отметка на 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 }