-
Notifications
You must be signed in to change notification settings - Fork 344
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
firewall: T4694: Adding GRE flags & fields matches to firewall rules #3637
Conversation
Please excuse the badly formatted commit message, this isn't intended as a final PR. |
0c9a2d9
to
e026344
Compare
3798c6d
to
0efd639
Compare
Fixed mistake in validator & rebased on current |
0efd639
to
c2dcb35
Compare
👍 VyOS CLI smoketests finished successfully! |
Testing is completed, clumsy design but operational. |
c2dcb35
to
9466ac2
Compare
Can you extend firewall smoketest, and include a test case for this setup? |
@nicolas-fort Added smoketests in a separate PR for both IPsec & GRE match changes - they're all in the same file, so there's merge conflicts in combined testing. Let me know if you'd like them split up into the separate PR branches instead. |
9466ac2
to
5e617b9
Compare
👍 |
Split smoketests back into their respective PRs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the UI and the implementation can be improved.
</valueHelp> | ||
<valueHelp> | ||
<format>8021ad</format> | ||
<description>Bridged Ethernet</description> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this description should be "802.1ad QinQ stacked VLAN" or similar. Saying "bridged" without explicitly mentioning "provider bridge" is just misleading, and even "provider bridge" isn't really a common term. "VLAN stacking" is intuitive and quite common.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm updating it to track the same terminology as include/vlan-protocol.xml.i (slightly less verbose): "Provider Bridging (IEEE 802.1ad, Q-in-Q)".
If you think it's useful to mention VLAN stacking as well when stuffing QinQ into GRE, it's no big effort for me to tweak again.
Since it's being tweaked, I'll add an alias for gretap 0x6558 as well, as it's an explicitly supported GRE interface type in VyOS.
src/validators/gre-protocol
Outdated
except ValueError: | ||
pass | ||
|
||
pattern = "!?\\b(ip|ip6|arp|vlan|8021q|8021ad)\\b" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This script is unnecessary, since the use case is already covered by the <regex>
validation mechanism, which is a part of the validate-value
executable and doesn't require spawning a subprocess (and spawning a Python interpreter is a notoriously slow operation).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Main reason I did this was for the multi-radix validation (0xNNNN syntax is pretty common for protocols and ethertypes).
The OCaml numeric validator doesn't like radix prefixes, I'll pack this all into a single regex for now - is that something that might be useful for the validator?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, Is there a neat or "proper" way to offer hex integers in valueHelp, or is it something that is best not done at all?
Right now I'm using:
<valueHelp>
<format>u32:0x0-0xFFFF</format>
<description>Ethernet protocol number (hex)</description>
</valueHelp>
This formats correctly in the completion under vbash. I picked through the vyatta-cfg node parser + completion scripts and couldn't immediately spot anywhere that definitely expects a base-10 integer, but I'm not familiar with the API and other internals that may treat those tags differently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The OCaml numeric validator doesn't like radix prefixes
The only reason for that is that I never thought it would be useful anywhere. It would be quite simple to add, although the UI for it is an interesting question. I made a task about it (https://vyos.dev/T6622), if you have any ideas, please leave a comment there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This formats correctly in the completion under vbash
This is defined in /etc/bash_completion.d/vyatta-cfg
case "$vtype" in
_*)
echo -n "${vtype#_}"
;;
txt)
echo -n '<text>'
;;
u32)
echo -n '<0-4294967295>'
;;
u32:*)
echo -n "<${vtype##u32:}>"
;;
...
Using
<valueHelp>
<format>u32:0x0-0xffff</format>
<description>Numeric IP port</description>
</valueHelp>
will yield <0x0-0xffff> Numeric IP port
and
<valueHelp>
<format>_0x0-0xffff</format>
<description>Numeric IP port</description>
</valueHelp>
will yield 0x0-0xffff Numeric IP port
5e617b9
to
dff46ca
Compare
Updated with requested changes, smoketests & generated rules look OK and re-ran through a short underlying test set with real traffic. I cannot figure out a way to do a CLI-level range validation on integers with a hex prefix (0xNNNN, for ethertype) without a custom validator, this has been moved into conf_mode. I can drop this convenience altogether if this doesn't match preferred style, but it's common to use these for ethertypes and protocol numbers. I've added 'gretap' as an ethertype alias in GRE matches, there doesn't seem to be a nice standard name for this (Cisco likes 'eogre', there's also 'gre-teb', 'l2gre' or 'teb'). I've stuck with the tunnel type name already used by VyOS. Code comments have been tweaked around a bit as well for clarity. |
I'm not entirely happy with my help text that follows the Potentially, can also switch to |
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
dff46ca
to
20ff312
Compare
Conflicts have been resolved. A maintainer will review the pull request shortly. |
CI integration ❌ failed! Details
|
I understand it this way: It should simply be: |
Can you please rebase this PR to the latest |
If I understand you - not quite, those are explicit checks for whether a flag bit is set or not set in the GRE header structure. That means there are 3 match states: "Don't care" (no node at all), "Is Set" or There are 2 flags we need to care about if we're checking for an optional key, because the packet structure changes depending on how they are set and there's no builtin lookups, so I'm doing raw transport header bitfields lookups to match the key value. The other flags are exposed more for completeness than anything else - somebody may find them useful. I don't really like the way this works, the protocol guts shouldn't need to be this exposed to the user. The alternatives would be using something as capable as BPF, since nftables can't handle it in a single rule (iptables with BPF expressions could do these multiple flagged-bitwise matches in a single rule), or re-engineering the nft config generation (and anything depending on it) to allow multiple rules in nft output from a single firewall config rule. The alternative I went with was simplicity of implementation and guiding the user if they're not sure - where it requires a setting for the "checksum" flag it gives a recommendation, and automatically assumes the "key" flag to be set if we want to match a key, disallowing an "unset" match. |
20ff312
to
0d55873
Compare
I do believe we should have a way to match only packets where the GRE key is not set, and the CLI for it will, unfortunately, be somewhat awkward because the issue is awkward. I think the current syntax is acceptable. |
Thanks for the clarification. |
* Only matching flags and fields used by modern RFC2890 "extended GRE" - this is backwards-compatible, but does not match all possible flags. * There are no nftables helpers for the GRE key field, which is critical to match individual tunnel sessions (more detail in the forum post) * nft expression syntax is not flexible enough for multiple field matches in a single rule and the key offset changes depending on flags. * Thus, clumsy compromise in requiring an explicit match on the "checksum" flag if a key is present, so we know where key will be. In most cases, nobody uses the checksum, but assuming it to be off or automatically adding a "not checksum" match unless told otherwise would be confusing * The automatic "flags key" check when specifying a key doesn't have similar validation, I added it first and it makes sense. I would still like to find a workaround to the "checksum" offset problem. * If we could add 2 rules from 1 config definition, we could match both cases with appropriate offsets, but this would break existing FW generation logic, logging, etc. * Added a "test_gre_match" smoketest
0d55873
to
60b0614
Compare
Applied requested changes & rebased |
Change Summary
Allow firewall rules to match flags and fields in GRE protocol headers, primarily, the "key" field.
Adding this will allow firewall rules to distinguish individual GRE sessions and apply appropriate policy, such as blocking sending or forwarding certain tunnels in the clear if IPsec is down.
Types of changes
Related Task(s)
Related PR(s)
Component(s) name
Proposed changes
I've covered some concerns I have about my implementation in the forum: https://forum.vyos.io/t/outbound-ipsec-filtering-by-firewall-would-like-some-dev-opinions/14710.
How to test
Starting firewall config (note ethtype 0x6558 is gretap):
This was a starting point, specific rules were fed directly into top level chains for testing outside of custom named chains and more yes/no logging firewall pairs were added to cover as many combinations of attributes & flags as possible.
The validators were also given exercise to make sure invalid flag/attribute combos weren't possible.
Smoketest result
Note, the groups failure below is also encountered in a clean rolling image:
Checklist: