Hello everyone,
I am in the process of evaluating the migration of a few routers from OPNSense to Vyos. The main reason for this being better/easier support for scripting and ansible. While I am more than happy with Vyos’ routing capabilities; there is one FW feature that is missing (Or I am missing something?)
In OPNSense I have been using “URL(IP)aliases” in FW rules to block inbound access from TOR exit nodes or certain geographical regions. Now, the latter can be achieved with Vyos builtin geoip feature and it works as it should. But what about implementing other blocklists (e.g. Tor exit nodes, DROP lists, etc ?)
A search on the forum suggests the use of external scripts which either
loop through a text file and feeding it line by line to the set firewall command (and therefore spamming the config) or
doing the same but feeding it to nft directly which results in those changes to be lost after reboot or even after making unrelated changes to the firewall.
Both are not viable options.
So far I have been using the 1.4.2 LTS version - which offers so called “dynamic-groups” but lacks documentation on how to properly populate them from an external URL or even a local text file.
The next step was trying the latest rolling release (dated from 25/6/6) which is supposed to offer remote groups. This feature comes close to what I was looking for but unfortunately it does not populate the group it creates.
I’m not going to be able to answer your last two questions in any meaningful way, but you are misunderstanding dynamic-groups.
The are described quite clearly here (at least I think it’s pretty clear)
The idea is you can have something happen in a firewall rule, i.e. a probe tries to hit port 22, and the source IP of that probe can be added to a dynamic firewall rule that you apply elsewhere.
Block all packets on the “bad probe” firewall group.
A packet comes in and hits a port 22 rule. The action is to add them to the “bad probe” group
The next packet from “bad probe” that comes in won’t make it to step 2, it’ll get dropped at step 1.
You can apply a timeout so an entry drops out of the group after a set time period, so you might block a badprobe ip for 24 hours etc.
As for the best way to import remote lists into VyOS, as you have noted the groundwork for that exists in 1.5/Rolling, but there is no such feature in 1.4.x. In 1.5 remote-groups should do what you want, but I don’t believe at the moment there’s any way for them to auto-update.
I use a custom-written script to import the spamhaus do-not-route list onto my device every 2-3 days, but it’s pretty clunky so I’m not going to share it (sorry)
You can read about the remote-group feature in 1.5 here. It will attempt to update the list periodically, and fallback to a cached version if the remote file can’t be fetched: Firewall groups — VyOS 1.5.x (circinus) documentation
For 1.4.2, any script you use to update nftables can be put in a post boot/commit script so it’s always updated when you reboot or make changes.
Thanks for the input so far. I do understand that 1.4.x has no built-in option to import remote lists. Regarding 1.5.x (rolling), I am not even able to populate the group once while the group is created so I wasn’t able to test whether it auto updates or not. A quick search has suggested that
firewall global-options resolver-interval 10
is able to achieve this. The issue at this point is that once I created a remote group as mentioned in my first post, the group does not get populated with the IPs/CIDRs which are contained in the remote list. The list can be fetched with curl and shows as one entry per line. So this should not be the issue. I have even tried to run a local webserver and created a file with a few entries manually which also is not read into the remote-group.
It’s working fine for me in 2025.06.04-0020-rolling:
set firewall group remote-group test_us url 'https://www.ipdeny.com/ipblocks/data/countries/us.zone'
vyos@vyos# sudo nft get element ip vyos_filter R_test_us { 4.2.2.2 }
table ip vyos_filter {
set R_test_us {
type ipv4_addr
flags interval
auto-merge
elements = { 3.0.0.0-4.255.255.255 }
}
}
Thank you for testing it.
I was not able to reproduce the same result on 2025.06.06-0019-rolling but will try to test this on 2025.06.04-0020-rolling in the next days.
My results are:
set firewall group remote-group test_us url 'https://www.ipdeny.com/ipblocks/data/countries/us.zone'
vyos@vyos-router# sudo nft get element ip vyos_filter R_test_us { 4.2.2.2 }
Error: Could not process rule: No such file or directory
get element ip vyos_filter R_test_us { 4.2.2.2 }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
May I ask why not all elements are listed inside the brackets?
I will look into this issue tomorrow. Maybe a last question for now:
I would have assumed that the set firewall group remote-group just read in the IPs/CIDRs regardless whether this group is actually used in a firewall rule. Your example suggests that you are actually using a rule called vyos_filter. Could this be the problem?
I did spin up a new VM with VERSION_ID="2025.06.06-0019-rolling" and only set hostname, timezone as well as giving the system a route to the internet and access to a DNS server. After that I was able to reproduce your result:
vyos@vyos-testing-1# sudo nft get element ip vyos_filter R_test_us { 4.2.2.2 }
table ip vyos_filter {
set R_test_us {
type ipv4_addr
flags interval
auto-merge
elements = { 3.0.0.0-4.255.255.255 }
}
vyos@vyos-testing-1# run sh firewall group test_us detail
Firewall Groups
Name | test_us
Description |
Type | remote_group
References | N/D
Members | 1.178.0.0/23 1.178.4.0-1.178.31.255 1.178.64.0/23
| 1.178.68.0-1.178.79.255 1.178.81.0/24 1.178.86.0-1.178.95.255
| 1.178.100.0-1.178.111.255 1.178.144.0-1.178.174.255
| 1.178.180.0-1.178.207.255 1.179.2.0/23 1.179.14.0/23
| 1.179.24.0-1.179.39.255 1.179.52.0-1.179.61.255 1.179.64.0/21
| 1.179.80.0/21 1.179.100.0-1.179.111.255 2.56.8.0/23 2.56.11.0/24
| 2.56.32.0/22 2.56.164.0/22 2.57.28.0/22 2.57.68.0/22 2.57.76.0/22
| 2.57.164.0/22 2.57.232.0/22 2.57.248.0/22 2.58.176.0/22
........................truncated...................(but all entries are there!)
Since this thread was about asking how to properly populate FW groups, I will mark your answer as the solution and suggest that this thread can be closed. I will continue to do some testing with this new feature, especially regarding the ability to automatically update this remote-group. Thanks to everyone who gave input on this issue.
Not yet. The goal at this stage was setting up FW groups that can be fed from remote sources and eventually being used in FW rules on the WAN interface (inbound).