Firewall groups today and tomorrow

Substantial work has been done by Marian Tudosoiu to bring IPv6 firewall groups to the current implementation of firewall configuration scripts even before we give it a complete rewrite. It's already merged into the current branch and is expected to be included in the 1.2.0-rc1 release. Now it's probably a good time to make a post about using firewall groups for those who haven't used them yet.

Of course there's still a lot of work to be done, such as integrating groups into NAT, which likely does require a complete rewrite to be feasible.

The concept is simple enough: instead of creating multiple rules that only differ in one address or port number, you create a group with all those addresses and ports, and reference it in a rule.

VyOS has three group types: address groups, network groups, and port groups. In 1.1.8 they can only be used with IPv4 firewall rulesets, including "policy route" rules.

Let's create some groups:
set firewall group port-group ManagementPorts port 22
set firewall group port-group ManagementPorts port 23
set firewall group port-group ManagementPorts port 443

set firewall group address-group Servers address 10.10.0.10
set firewall group address-group Servers address 10.10.0.15
set firewall group address-group Servers address 10.10.0.20

set firewall group network-group TrustedNets network 192.168.5.0/24
set firewall group network-group TrustedNets network 172.18.19.128/25
set firewall group network-group TrustedNets network 10.20.30.144/32

Now we can create a ruleset that uses them. Let's make a rule that references nothing but groups:

set firewall name DMZ-In rule 10 action accept
set firewall name DMZ-In rule 10 protocol tcp
set firewall name DMZ-In rule 10 source group network-group TrustedNets
set firewall name DMZ-In rule 10 destination group port-group ManagementPorts
set firewall name DMZ-In rule 10 destination group address-group Servers

An important part is that you can modify groups on the fly without updating any rules.

As you can see, groups is a simple concept that can be learnt in minutes. Once they are in IPv6 and NAT, their use will be very similar.

Using the "policy route" and packet marking for custom QoS matches

There is only that much you can do in a QoS rules to describe the traffic you want it to match. There's DCP, source/destination, and protocol, and that's enough to cover most of the use cases. Most, but not all. Fortunately, they can also match packet marks and that's what enables creating custom matches.

Packet marks are numeric values set by Netfilter rules that are local to the router and can be used as match criteria in other Netfilter rules and many other components of the Linux kernel (ip, tc, and so on).

Suppose you have a few phones in the office and you want to prioritize their VoIP traffic. You could create a QoS match for each of them, but it's quite some config duplication, which will only get worse when you add more phones. If you find a way to group those addresses in one match, wouldn't it be nice? Sadly, there's no such option in QoS. Firewall can use address groups though, so we can make the QoS rule match a packet mark (e.g. 100) and set that mark to traffic from the phones.

# show traffic-policy 
 priority-queue VoIP {
     class 7 {
         match SIP {
             mark 100
         }
         queue-type drop-tail
     }
     default {
         queue-type fair-queue
     }
 }

Now the confusing bit. Where do we set the mark? Around Vyatta 6.5, an unfortunate design decision was made: "firewall modify" was moved under overly narrow and not so obvious "policy route". Sadly we are stuck with it for the time being because it's not so easy to automatically convert the syntax for upgrades. But, its odd name notwithstanding, it still does the job.

Let's create an address group and a "policy route" instance that sets the mark 100:

# show firewall group 
 address-group Phones {
     address 10.4.5.10
     address 10.4.5.11
     address 10.4.5.12
 }
[edit]
# show policy route 
 route VoIP {
     rule 10 {
         set {
             mark 100
         }
         source {
             group {
                 address-group Phones
             }
         }
     }
 }

Now we need to assign the QoS ruleset to our WAN and the "policy route" instance to our LAN interface:

set interfaces ethernet eth0 policy route VoIP
set interfaces ethernet eth1 traffic-policy out VoIP

You can as well take advantage of "policy route" ruleset options for time-based filtering or matching related connections. Besides, you can use it to set DSCP values in case your QoS setup is on a different router:

set policy route Foo rule 10 set dscp 46