pyroute2
pyroute2 copied to clipboard
How to add ip address into nftables's sets?
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')
@inemajo do you possess this secret knowledge?
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)]}]
]}
]
}
)
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
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