Page MenuHomeVyOS Platform

policy based routing tcp flags issue
Closed, ResolvedPublicBUG

Description

policy based routing having some issues with current nftables implementation in rolling release.

for example basic tcp-mss policy:

stannert@vyos# show policy route
+route tcpmssclamp {
+    rule 1 {
+        protocol tcp
+        set {
+            tcp-mss 1452
+        }
+        tcp {
+            flags SYN
+        }
+    }
+}

on committing:

stannert@vyos# commit
[ policy route tcpmssclamp ]
Failed to apply policy based routing

[[policy route tcpmssclamp]] failed
Commit failed
[edit]

nftables_policy.conf

stannert@vyos# cat /run/nftables_policy.conf
#!/usr/sbin/nft -f


include "/run/nftables_defines.conf"

table ip mangle {
    chain VYOS_PBR_tcpmssclamp {
        meta l4proto tcp tcp flags & (SYN) == SYN counter tcp option maxseg size set 1452 return comment "tcpmssclamp-1"
        counter return
    }
}

table ip6 mangle {
}[edit]
stannert@vyos# nft -c -f /run/nftables_policy.conf
/run/nftables_policy.conf:8:39-41: Error: Could not parse TCP flag
        meta l4proto tcp tcp flags & (SYN) == SYN counter tcp option maxseg size set 1452 return comment "tcpmssclamp-1"
                                      ^^^
[edit]

if I edit the nftables_policy.conf and write the "SYN" in lowercase, then it's working.
from vyos cli i can set "tcp flags syn" but if I commit with lowercase "syn" i get an commit error aswell:

Traceback (most recent call last):
  File "/usr/libexec/vyos/conf_mode/policy-route.py", line 226, in <module>
    verify(c)
  File "/usr/libexec/vyos/conf_mode/policy-route.py", line 141, in verify
    verify_rule(policy, rule_conf, ipv6)
  File "/usr/libexec/vyos/conf_mode/policy-route.py", line 100, in verify_rule
    raise ConfigError(f'{name} rule {rule_id}: TCP SYN flag must be set to modify TCP-MSS')
NameError: name 'name' is not defined

So I guess nftables expects lowercase tcp flags (syn,fin,ack,rst) instead of uppercase.
But validator wants uppercase, after changing "policy-route.py" in line 99:

Before:
if not tcp_flags or 'SYN' not in tcp_flags.split(","):

After:
if not tcp_flags or 'syn' not in tcp_flags.split(","):

And changing configuration via VyOS CLI to:

stannert@vyos# compare
[edit policy]
+route tcpmssclamp {
+    rule 1 {
+        protocol tcp
+        set {
+            tcp-mss 1452
+        }
+        tcp {
+            flags syn
+        }
+    }
+}
[edit]

the commit is working.
So possible to change the "policy-route.py" file but the auto completion needs to be changed then aswell and I don't know if there are other implementations with uppercase values.

stannert@vyos# set policy route tcpmssclamp rule 1 tcp flags
Possible completions:
   <text>       TCP flags to match


  Allowed values for TCP flags : SYN ACK FIN RST URG PSH ALL
  When specifying more than one flag, flags should be comma-separated.
 For example : value of 'SYN,!ACK,!FIN,!RST' will only match packets with
  the SYN flag set, and the ACK, FIN and RST flags unset
[edit]
stannert@vyos# run show version

Version:          VyOS 1.4-rolling-202201120317
Release train:    sagitta

cheers

Details

Difficulty level
Unknown (require assessment)
Version
VyOS 1.4-rolling-202201120317
Why the issue appeared?
Will be filled on close
Is it a breaking change?
Unspecified (possibly destroys the router)
Issue type
Bug (incorrect behavior)

Event Timeline

sarthurdev changed the task status from Open to In progress.Jan 13 2022, 11:55 AM
sarthurdev claimed this task.
sarthurdev added a subscriber: sarthurdev.

Thanks for the report, working on the fix now.

Think 2 flag options should be added.
According to nft wiki these are all the flags that nft could match: tcp flags { fin, syn, rst, psh, ack, urg, ecn, cwr}

Currently, last 2 flags are not available in VyOS.

Wiki reference: https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes#Tcp

TCP Flags seems to be working on firewall filter config.

vyos@vyos:~$ show config comm | grep fire
set firewall name FOO rule 10 action 'accept'
set firewall name FOO rule 10 protocol 'tcp'
set firewall name FOO rule 10 tcp flags ack
set firewall name FOO rule 10 tcp flags not ecn
set firewall name FOO rule 10 tcp flags syn

vyos@vyos:~$ sudo nft list chain ip filter FOO
table ip filter {
	chain FOO {
		tcp flags & (syn | ack | ecn) == syn | ack counter packets 0 bytes 0 return comment "FOO-10"
		return
	}
}

But scenario of this task is not working

vyos@vyos# compare
[edit policy]
+route TEST {
+    rule 1 {
+        protocol tcp
+        set {
+            tcp-mss 1452
+        }
+        tcp {
+            flags {
+                syn
+            }
+        }
+    }
+}
[edit]
vyos@vyos# commit
[ policy route TEST ]
Failed to apply policy based routing

[[policy route TEST]] failed
Commit failed

Content of /run/nftables_policy.conf (omitting ip6 mangle)

vyos@vyos# cat /run/nftables_policy.conf 
#!/usr/sbin/nft -f


include "/run/nftables_defines.conf"

table ip mangle {
    chain VYOS_PBR_PREROUTING {
        type filter hook prerouting priority -150; policy accept;
    }
    chain VYOS_PBR_POSTROUTING {
        type filter hook postrouting priority -150; policy accept;
    }
    chain VYOS_PBR_TEST {
        meta l4proto  tcp tcp flags & () == syn counter tcp option maxseg size set 1452 return comment "TEST-1"
        counter return
    }
}