pyroute2 icon indicating copy to clipboard operation
pyroute2 copied to clipboard

How to add ip address into nftables's sets?

Open rexzhang opened this issue 2 years ago • 3 comments

I have pre-created the table and sets.

>>> from pyroute2.nftables.main import NFTables
>>> nft=NFTables(nfgen_family=7)
>>> nft.get_sets()
({'nfgen_family': 7, 'version': 0, 'res_id': 214, 'attrs': [('NFTA_SET_TABLE', 'PiRouter'), ('NFTA_SET_NAME', 'BypassIP'), ('NFTA_SET_HANDLE', 1), ('NFTA_SET_FLAGS', frozenset({'NFT_SET_INTERVAL'})), ('NFTA_SET_KEY_TYPE', 7), ('NFTA_SET_KEY_LEN', 4), ('NFTA_SET_USERDATA', '00:04:02:00:00:00'), ('NFTA_SET_DESC', {'attrs': []})], 'header': {'length': 104, 'type': 2569, 'flags': 2, 'sequence_number': 255, 'pid': 2674516886, 'error': None, 'target': 'localhost', 'stats': Stats(qsize=0, delta=0, delay=0)}}, {'nfgen_family': 7, 'version': 0, 'res_id': 214, 'attrs': [('NFTA_SET_TABLE', 'PiRouter'), ('NFTA_SET_NAME', 'BypassIP6'), ('NFTA_SET_HANDLE', 2), ('NFTA_SET_FLAGS', frozenset({'NFT_SET_INTERVAL'})), ('NFTA_SET_KEY_TYPE', 8), ('NFTA_SET_KEY_LEN', 16), ('NFTA_SET_USERDATA', '00:04:02:00:00:00'), ('NFTA_SET_DESC', {'attrs': []})], 'header': {'length': 104, 'type': 2569, 'flags': 2, 'sequence_number': 255, 'pid': 2674516886, 'error': None, 'target': 'localhost', 'stats': Stats(qsize=0, delta=0, delay=0)}}, {'nfgen_family': 7, 'version': 0, 'res_id': 214, 'attrs': [('NFTA_SET_TABLE', 'PiRouter'), ('NFTA_SET_NAME', 'SelfMAC'), ('NFTA_SET_HANDLE', 3), ('NFTA_SET_KEY_TYPE', 9), ('NFTA_SET_KEY_LEN', 6), ('NFTA_SET_USERDATA', '00:04:02:00:00:00'), ('NFTA_SET_DESC', {'attrs': []})], 'header': {'length': 92, 'type': 2569, 'flags': 2, 'sequence_number': 255, 'pid': 2674516886, 'error': None, 'target': 'localhost', 'stats': Stats(qsize=0, delta=0, delay=0)}}, {'nfgen_family': 7, 'version': 0, 'res_id': 214, 'attrs': [('NFTA_SET_TABLE', 'PiRouter'), ('NFTA_SET_NAME', 'TargetIP'), ('NFTA_SET_HANDLE', 4), ('NFTA_SET_KEY_TYPE', 7), ('NFTA_SET_KEY_LEN', 4), ('NFTA_SET_USERDATA', '00:04:02:00:00:00'), ('NFTA_SET_DESC', {'attrs': []})], 'header': {'length': 96, 'type': 2569, 'flags': 2, 'sequence_number': 255, 'pid': 2674516886, 'error': None, 'target': 'localhost', 'stats': Stats(qsize=0, delta=0, delay=0)}}, {'nfgen_family': 7, 'version': 0, 'res_id': 214, 'attrs': [('NFTA_SET_TABLE', 'PiRouter'), ('NFTA_SET_NAME', 'TargetIP6'), ('NFTA_SET_HANDLE', 5), ('NFTA_SET_KEY_TYPE', 8), ('NFTA_SET_KEY_LEN', 16), ('NFTA_SET_USERDATA', '00:04:02:00:00:00'), ('NFTA_SET_DESC', {'attrs': []})], 'header': {'length': 96, 'type': 2569, 'flags': 2, 'sequence_number': 255, 'pid': 2674516886, 'error': None, 'target': 'localhost', 'stats': Stats(qsize=0, delta=0, delay=0)}}, {'nfgen_family': 7, 'version': 0, 'res_id': 214, 'attrs': [('NFTA_SET_TABLE', 'PiRouter'), ('NFTA_SET_NAME', 'ClientMAC'), ('NFTA_SET_HANDLE', 6), ('NFTA_SET_KEY_TYPE', 9), ('NFTA_SET_KEY_LEN', 6), ('NFTA_SET_USERDATA', '00:04:02:00:00:00'), ('NFTA_SET_DESC', {'attrs': []})], 'header': {'length': 96, 'type': 2569, 'flags': 2, 'sequence_number': 255, 'pid': 2674516886, 'error': None, 'target': 'localhost', 'stats': Stats(qsize=0, delta=0, delay=0)}}, {'nfgen_family': 7, 'version': 0, 'res_id': 214, 'attrs': [('NFTA_SET_TABLE', 'PiRouter'), ('NFTA_SET_NAME', 'ClientIP'), ('NFTA_SET_HANDLE', 7), ('NFTA_SET_KEY_TYPE', 7), ('NFTA_SET_KEY_LEN', 4), ('NFTA_SET_USERDATA', '00:04:02:00:00:00'), ('NFTA_SET_DESC', {'attrs': []})], 'header': {'length': 96, 'type': 2569, 'flags': 2, 'sequence_number': 255, 'pid': 2674516886, 'error': None, 'target': 'localhost', 'stats': Stats(qsize=0, delta=0, delay=0)}}, {'nfgen_family': 7, 'version': 0, 'res_id': 214, 'attrs': [('NFTA_SET_TABLE', 'PiRouter'), ('NFTA_SET_NAME', '__set0'), ('NFTA_SET_HANDLE', 13), ('NFTA_SET_FLAGS', frozenset({'NFT_SET_CONSTANT', 'NFT_SET_ANONYMOUS'})), ('NFTA_SET_KEY_TYPE', 9), ('NFTA_SET_KEY_LEN', 6), ('NFTA_SET_USERDATA', '00:04:02:00:00:00'), ('NFTA_SET_DESC', {'attrs': []})], 'header': {'length': 100, 'type': 2569, 'flags': 2, 'sequence_number': 255, 'pid': 2674516886, 'error': None, 'target': 'localhost', 'stats': Stats(qsize=0, delta=0, delay=0)}})

Want to replace the following command:

nft add element ip TABLE SET { 1.1.1.1 }

But...

>>> from pyroute2.nftables.main import NFTables
>>>
>>> table_name = "PiRouter"
>>> family_name= "bridge"
>>> set_name ="TargetIP"
>>> ip_address_list=["1.1.1.1",]
>>>
>>> nft=NFTables(nfgen_family=7)
>>> nft.begin()
True
>>> nft.rule(
...     cmd="add",
...     table=table_name,
...     family=family_name,
...     set=set_name,
...     expressions=ip_address_list,
... )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.9/dist-packages/pyroute2/nftables/main.py", line 127, in rule
    return self._command(nft_rule_msg, commands, cmd, kwarg)
  File "/usr/local/lib/python3.9/dist-packages/pyroute2/netlink/nfnetlink/nftsocket.py", line 1151, in _command
    self.nlm_request_batch(messages, noraise=(flags & NLM_F_ACK) == 0)
  File "/usr/local/lib/python3.9/dist-packages/pyroute2/netlink/nlsocket.py", line 415, in nlm_request_batch
    return tuple(self._genlm_request_batch(*argv, **kwarg))
  File "/usr/local/lib/python3.9/dist-packages/pyroute2/netlink/nlsocket.py", line 950, in nlm_request_batch
    for msg in self.get(msg_seq=seq, noraise=noraise):
  File "/usr/local/lib/python3.9/dist-packages/pyroute2/netlink/nlsocket.py", line 406, in get
    return tuple(self._genlm_get(*argv, **kwarg))
  File "/usr/local/lib/python3.9/dist-packages/pyroute2/netlink/nlsocket.py", line 770, in get
    raise msg['header']['error']
pyroute2.netlink.exceptions.NetlinkError: (22, 'Invalid argument')

rexzhang avatar Aug 31 '22 16:08 rexzhang

@inemajo do you possess this secret knowledge?

svinota avatar Sep 01 '22 11:09 svinota

Hello, rule api of nftables is not for managing sets. Set element get/set is currently not implemented in highlevel API, Here is a ugly exemple for getting and adding element to a nftables set:

I will try to implement it shortly

import socket
from pyroute2.nftables.main import NFTables
from pr2modules.netlink.nfnetlink import nfgen_msg
from pr2modules.netlink.nfnetlink.nftsocket import NFT_MSG_NEWSETELEM
from pr2modules.netlink.nfnetlink.nftsocket import NFT_MSG_GETSETELEM
from pr2modules.netlink.nfnetlink.nftsocket import nft_set_msg
from pr2modules.netlink.nfnetlink.nftsocket import nft_set_elem_list_msg

table_name = "filter"
set_name = "test1"
ip_address = socket.inet_aton("1.1.1.1")

print("--- GETTING ELEMENTS OF SET ---")
msg = nft_set_elem_list_msg()
msg['attrs'] = [
    ["NFTA_SET_ELEM_LIST_TABLE", table_name],
    ["NFTA_SET_ELEM_LIST_SET", set_name]
]
print(NFTables().request_get(msg, NFT_MSG_GETSETELEM))



print("--- ADDING ELEMENTS TO SET ---")
NFTables()._command(
    nft_set_elem_list_msg,
    {"add": NFT_MSG_NEWSETELEM},
    "add",
    {
        "NFTA_SET_ELEM_LIST_TABLE": table_name,
        "NFTA_SET_ELEM_LIST_SET": set_name,
        'NFTA_SET_ELEM_LIST_ELEMENTS': [
            {'attrs': [
                    ['NFTA_SET_ELEM_KEY', {'attrs': [('NFTA_DATA_VALUE', ip_address)]}]
            ]}
        ]
    }
)

inemajo avatar Sep 01 '22 13:09 inemajo

this sample cannot work on Pi3B+ / Linux pirouter 5.15.61-v8+ #1579 SMP PREEMPT Fri Aug 26 11:16:44 BST 2022 aarch64 GNU/Linux / nftables v0.9.8 (E.D.S.)

Looking forward to the high-level API

rexzhang avatar Sep 03 '22 05:09 rexzhang

thank you! it's work!

from pyroute2.netlink.nfnetlink.nftsocket import NFPROTO_BRIDGE
from pyroute2.nftables.main import NFTables

with NFTables(nfgen_family=NFPROTO_BRIDGE) as nft:
    message = nft.set_elems(
        "add", table=table_name, set=set_name, elements=ip_address_list
    )

test on pyroute2 v0.7.6

rexzhang avatar Mar 25 '23 06:03 rexzhang