Groups, egress and a shared chain
Traffic through the router gets the same treatment, using the same groups.
Egress filtering
Most forward filters only look inward. This one also limits what the LAN may do outward: the LAN may browse the web (WEB-PORTS), and ping, but nothing else leaves. If a machine on the LAN is infected, it can't send spam, scan the internet or open a remote shell to its owner on some random port. It costs one rule and a port-group.
Inbound, only the LAN's public web server (198.51.100.10) on the web ports is reachable.
One chain, two hooks
A blocklist is needed in both directions: a blocked host shouldn't reach the LAN or the router. Instead of writing it twice, it's a named chain, BLOCKLIST-CHECK, jumped to from rule 5 of both the input and forward filters. Its default-action return sends everything that isn't on the list back to the next rule of whichever filter jumped there.
Testing it
lanhost can browse home, but its SSH attempt to home times out. A closed port would have answered at once with connection refused; a timeout means a firewall silently dropped the packet. home reaches the LAN web server. The scanner can't reach the LAN web server or even ping the router.
show firewall group lists each group with every rule that uses it, which is how you check what a change to a group will affect.
set firewall group address-group BLOCKLIST address '192.0.2.66'
set firewall group interface-group LAN-IFS interface 'eth1'
set firewall group port-group WEB-PORTS port '80'
set firewall group port-group WEB-PORTS port '443'
set firewall ipv4 name BLOCKLIST-CHECK default-action 'return'
set firewall ipv4 name BLOCKLIST-CHECK description 'Shared by input and forward'
set firewall ipv4 name BLOCKLIST-CHECK rule 10 action 'drop'
set firewall ipv4 name BLOCKLIST-CHECK rule 10 source group address-group 'BLOCKLIST'
set firewall ipv4 name BLOCKLIST-CHECK rule 10 log
set firewall ipv4 input filter rule 5 action 'jump'
set firewall ipv4 input filter rule 5 jump-target 'BLOCKLIST-CHECK'
set firewall ipv4 forward filter default-action 'drop'
set firewall ipv4 forward filter rule 5 action 'jump'
set firewall ipv4 forward filter rule 5 jump-target 'BLOCKLIST-CHECK'
set firewall ipv4 forward filter rule 10 action 'accept'
set firewall ipv4 forward filter rule 10 description 'LAN may browse the web'
set firewall ipv4 forward filter rule 10 inbound-interface group 'LAN-IFS'
set firewall ipv4 forward filter rule 10 protocol 'tcp'
set firewall ipv4 forward filter rule 10 destination group port-group 'WEB-PORTS'
set firewall ipv4 forward filter rule 20 action 'accept'
set firewall ipv4 forward filter rule 20 protocol 'icmp'
set firewall ipv4 forward filter rule 30 action 'accept'
set firewall ipv4 forward filter rule 30 description 'The public web server on the LAN'
set firewall ipv4 forward filter rule 30 outbound-interface group 'LAN-IFS'
set firewall ipv4 forward filter rule 30 destination address '198.51.100.10'
set firewall ipv4 forward filter rule 30 protocol 'tcp'
set firewall ipv4 forward filter rule 30 destination group port-group 'WEB-PORTS'- Lines 1–4: More groups: the blocklist, the LAN interfaces and the web ports.
- Lines 5–9: The shared chain: drop and log listed sources, otherwise
returnto whoever jumped here. - Lines 10–11: Used by the input filter…
- Lines 12–14: …and the forward filter, before anything else.
- Lines 15–19: Egress: the LAN may only use the web ports outward.
- Lines 22–27: Inbound: only the public web server, on the web ports.
root@lanhost:~# curl -s -m 3 http://192.0.2.10/
hello from home
root@lanhost:~# nc -zv -w 3 192.0.2.10 22 2>&1 || echo "blocked"
nc: connect to 192.0.2.10 port 22 (tcp) timed out: Operation now in progress
blocked
root@home:~# curl -s -m 3 http://198.51.100.10/
hello from lanhost
root@scanner:~# curl -s -m 3 http://198.51.100.10/ || echo "no answer"
no answer
root@scanner:~# ping -c 2 -W 1 203.0.113.2 | tail -2
2 packets transmitted, 0 received, 100% packet loss, time 1043ms- Lines 1–2: LAN to the web: allowed.
- Lines 4–6: LAN to SSH on the internet: a timeout, the sign of a silent drop.
- Lines 8–9: Internet to the LAN's web server: allowed.
- Lines 11–15: The blocklisted scanner: no web, and no ping to the router either.
vyos@R1:~$ show firewall ipv4 forward filter
Ruleset Information
---------------------------------
ipv4 Firewall "forward filter"
Rule Action Protocol Packets Bytes Conditions
------- -------- ---------- --------- ------- ------------------------------------------------------------------------
5 jump all 8 480 jump NAME_BLOCKLIST-CHECK
10 accept tcp 1 60 tcp dport @P_WEB-PORTS iifname @I_LAN-IFS accept
20 accept icmp 0 0 meta l4proto icmp accept
30 accept tcp 1 60 ip daddr 198.51.100.10 tcp dport @P_WEB-PORTS oifname @I_LAN-IFS accept
default drop all 3 180 comment "FWD-filter default-action "
vyos@R1:~$ show firewall ipv4 name BLOCKLIST-CHECK
Ruleset Information
---------------------------------
ipv4 Firewall "name BLOCKLIST-CHECK"
Rule Action Protocol Packets Bytes Conditions
------- -------- ---------- --------- ------- ---------------------------------------------------------------
10 drop all 5 348 ip saddr @A_BLOCKLIST prefix "[ipv4-NAM-BLOCKLIST-CHECK-10-D]"
default return all 15 900 comment "NAM-BLOCKLIST-CHECK default-action "
vyos@R1:~$ show firewall group
Firewall Groups
Name Type References Members
----------- --------------- ---------------------------- ------------
ADMIN-HOMES address_group ipv4-name-SSH-IN-30 192.0.2.10
BLOCKLIST address_group ipv4-name-BLOCKLIST-CHECK-10 192.0.2.66
LAN-IFS interface_group ipv4-forward-filter-10 eth1
ipv4-forward-filter-30
MGMT-NETS network_group ipv4-name-SSH-IN-10 10.99.0.0/24
WEB-PORTS port_group ipv4-forward-filter-10 443
ipv4-forward-filter-30 80- Line 9: Only new connections reach rule 5; the state policy accepted the rest.
- Line 13: lanhost's SSH attempt, dropped by the default.
- Lines 23–24: The blocklist chain, hit from both hooks; everything else returned.
- Lines 26–37: Each group, with every rule that uses it.
Check your understanding
Why did lanhost's SSH attempt time out, rather than fail with connection refused?
- R1's forward filter dropped the packet silently, so nothing ever answered.
- home's SSH server was too slow.
- The rate limit on R1.
- A missing route.