Page MenuHomeVyOS Platform

Add ability to create raw nftables rule
Closed, WontfixPublicFEATURE REQUEST

Description

It could be useful to allow an nft rule to be created from raw nftables syntax.. This would allow for complex configurations for users while they await native implementation of nftables syntax.

Configuration could look something like:

set firewall ipv4 forward filter rule 10 action nft-rule
set firewall ipv4 forward filter rule 10 nft-rule "ct state vmap { established : accept, related : accept, invalid : drop }"

Details

Version
-
Is it a breaking change?
Unspecified (possibly destroys the router)
Issue type
Feature (new functionality)

Event Timeline

Unknown Object (User) triaged this task as Normal priority.Jun 24 2025, 9:55 AM
Viacheslav subscribed.

This way, it is simple to handle native nft commands with custom tables, then use them in the VyOS CLI.
I'm not expecting this feature to be implemented in the suggested format.

This way, it is simple to handle native nft commands with custom tables, then use them in the VyOS CLI.
I'm not expecting this feature to be implemented in the suggested format.

@Viacheslav

One thought I had was something like:

Syntax
set firewall custom-rules from-file "/config/nft-configs/my-custom-rules.nft" revision 1
Loading the config

This would be very easy to simply append the contents of the file to the existing nftables.conf file that is generated in the render pipeline. There is already a -c option in the apply stage of the firewall.py conf-mode script that would validate correct formatting of the contents in the custom file:

def apply(firewall):
    # Use nft -c option to check current configuration file
    completed_process = subp_run(['nft', '-c', '--file', nftables_conf], capture_output=True)

This even allows applying multiple custom-rules files like:

set firewall custom-rules from-file "/config/nft-configs/flow-vmap.nft" revision 1
set firewall custom-rules from-file "/config/nft-configs/copp-policing.nft" revision 1
Ensuring versioning for rollback

The revision number would be used for the ability to rollback any config that was applied in the custom files. So the contents of my-custom-rules.nft would only be loaded when the revision number changes. A file named my-custom-rules.nft.rev1 would be created, and that is the file that would be appended to nftables.conf unless the revision file doesn't exist, which indicates a new revision. Each time the firewall.py script is called, it will check if the revision file already exists, and will continue to use that.

Verification checks

Potential verification checks:

"Revsion '2' was previously used for this ruleset, revisions must be historically unique" - Keeping these unique allows rolling back changes applied to the custom rules.
"File is not located within the '/config' directory. This file will not survive a version change"

There are some other potential verification measures, but I think it would make more sense to simply allow the nft -c to handle those. For instance, you don't want someone changing VYOS_FORWARD_filter to an input or output hook, but the nft -c check will already prevent that.

Potential use case:

Imagine a customer with a very strict policy for allowed traffic. If they have 10k rules, that would not only make the processing of traffic very slow, but the config load and commit times would be horrible in VyOS. They could instead load the config from a file, and apply that to a map, which is a feature not currently in VyOS.

They could simply manage a CSV with values for: srcip, dstip, dstport, proto, and run that against a python script that will output their nft file. All of those would then get added to a map which has O(1) lookup. So this would solve both the long commit/load times of the config, as well as the slow processing of rules.

The output file would look something like:

delete table ip my_custom_table
table ip my_custom_table {
        map flow_vmap {
                type ipv4_addr . ipv4_addr . inet_service . inet_proto : verdict
                flags interval
                counter
                elements = { 10.5.0.100 . 10.100.0.55 . 22 . tcp : accept,
                             10.5.0.101 . 10.100.0.55 . 23 . tcp : accept,
                             10.5.0.102 . 10.100.0.55 . 443 . tcp : accept }
        }

        chain my_custom_chain {
                type filter hook forward priority filter+15; policy drop;
                ip saddr . ip daddr . tcp dport . meta l4proto vmap @flow_vmap comment "TCP based Verdict Map"
        }
}

These were the times to generate a file with 10k elements in a map, as well as the time to apply that to nftables:

root@vyos:/home/vyos# time python3 test.py -n 10000
Wrote 10000 elements to flow_vmap.nft (table inet vyos_test, map flow_vmap)

real    0m0.047s
user    0m0.045s
sys     0m0.002s

root@vyos:/home/vyos# time nft -f flow_vmap.nft 

real    0m0.095s
user    0m0.034s
sys     0m0.055s
dmbaturin claimed this task.
dmbaturin subscribed.

The PR was rejected after a discussion and a decision that we shouldn't add more escape hatches from the CLI and should focus on improving the CLI itself instead.