Skip to content
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

T6687: add fqdn support to nat rules. #4024

Merged
merged 1 commit into from
Sep 30, 2024
Merged

Conversation

nicolas-fort
Copy link
Contributor

Change Summary

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes)
  • Migration from an old Vyatta component to vyos-1x, please link to related PR inside obsoleted component
  • Other (please describe):

Related Task(s)

Related PR(s)

Component(s) name

nat

Proposed changes

How to test

vyos@fqdn-nat# run show config comm | grep nat
set nat destination rule 10 destination fqdn 'vyos.dev'
set nat destination rule 10 inbound-interface name 'eth2'
set nat destination rule 10 translation address '198.51.100.55'
set system host-name 'fqdn-nat'
[edit]
vyos@fqdn-nat# sudo nft -s list table ip vyos_nat
table ip vyos_nat {
        set FQDN_nat_destination_10_d {
                type ipv4_addr
                flags interval
                elements = { 104.18.2.133, 104.18.3.133 }
        }

        chain PREROUTING {
                type nat hook prerouting priority dstnat; policy accept;
                counter jump VYOS_PRE_DNAT_HOOK
                iifname "eth2" ip daddr @FQDN_nat_destination_10_d counter dnat to 198.51.100.55 comment "DST-NAT-10"
        }

        chain POSTROUTING {
                type nat hook postrouting priority srcnat; policy accept;
                counter jump VYOS_PRE_SNAT_HOOK
        }

        chain VYOS_PRE_DNAT_HOOK {
                return
        }

        chain VYOS_PRE_SNAT_HOOK {
                return
        }
}
[edit]
vyos@fqdn-nat# sudo ps aux | grep vyos-domain
root        2928  0.6  5.1  64160 51124 ?        Ss   17:56   0:00 /usr/bin/python3 -u /usr/libexec/vyos/vyos-domain-resolver.py
vyos        3134  0.0  0.2   6332  2048 ttyS0    S+   17:57   0:00 grep vyos-domain
[edit]
vyos@fqdn-nat# 

Smoketest result

  • test_firewall.py --> OK
  • test_nat.py --> OK

Checklist:

  • I have read the CONTRIBUTING document
  • I have linked this PR to one or more Phabricator Task(s)
  • I have run the components SMOKETESTS if applicable
  • My commit headlines contain a valid Task id
  • My change requires a change to the documentation
  • I have updated the documentation accordingly

Copy link

github-actions bot commented Aug 30, 2024

👍
No issues in PR Title / Commit Title

Copy link

github-actions bot commented Aug 30, 2024

✅ No issues found in unused-imports check.. Please refer the workflow run

@@ -43,4 +56,8 @@ table ip vyos_nat {

{{ group_tmpl.groups(firewall_group, False, True) }}
}

{% if ip_fqdn.items() %}
# use-domain-resolver=yes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does nothing
Is it correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicolas-fort The question is why the line is always generated with a # before it — that means the line is commented out and will not have any effect, unless Viacheslav and I are missing anything about the config file syntax.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, to nftables it does nothing. As you said, it's always generated with #, so it's a comment. But while applying firewall and nat rules, it checks if that comment is present in those files, in order to start/stop vyos-domain-resolver service.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dmbaturin The line seems to be picked up by a file contents check in the conf script.

Though not sure why the ip_fqdn boolean check is insufficient here @nicolas-fort ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vyos-domain-resolver now updates domains and/or fqdn entries, if they are configured in firewall and NAT.

  1. While parsing firewall rules, if fqdn or group-domains are used, then this comment is added to /run/nftables.conf as a flag that will be checked by nat scripts (of course, if nat is configured)
  2. While parsing nat rules, if fqdn are used, then this comment is added to /run/nftables_nat.conf as a flag that will be checked by firewall scripts (of course, if firewall is configured).

Since only once service handles this translations, while parsing one part of the config (for example firewall), we need to know if fqdn are configured in the other feature (nat).

I thought that would be better this approach, and check if comments are present in those files in order to decide to stop/start vypos-domain-resolver service, rather than while parsing one feature (for example nat), also grab the full configuration of the other feature (in the example would be firewall), and then decide if the service should be started or stopped.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a bad feeling about such action at a distance, to be fair. At the very least it should be documented in the generated file, why a line that has no effect within that file is included in it.

But I think we should look for other solutions before we take this route. In the worst case, can we just enable the resolver daemon by default? It does nothing when there are no domain groups, and doesn't take much memory or CPU when idle, does it?

c-po
c-po previously requested changes Sep 3, 2024
python/vyos/firewall.py Outdated Show resolved Hide resolved
@nicolas-fort
Copy link
Contributor Author

I'm marking this one as Draft while working on changes.

@sever-sever
Copy link
Member

Fails:

vyos@r14# compare 
+ nat {
+     source {
+         rule 100 {
+             destination {
+                 fqdn "google.com"
+             }
+             outbound-interface {
+                 name "eth0"
+             }
+             source {
+                 address "10.0.0.0/24"
+             }
+             translation {
+                 address "masquerade"
+             }
+         }
+     }
+ }

[edit]
vyos@r14# commit

Configuration file errors encountered!

[[nat]] failed
Commit failed
[edit]
vyos@r14# 

cat /run/nftables_nat.conf

#!/usr/sbin/nft -f


delete table ip vyos_nat
table ip vyos_nat {
    #
    # Destination NAT rules build up here
    #
    chain PREROUTING {
        type nat hook prerouting priority -100; policy accept;
        counter jump VYOS_PRE_DNAT_HOOK
    }
    set FQDN_nat_source_100_d {
        type ipv4_addr
        flags interval
    }

    #
    # Source NAT rules build up here
    #
    chain POSTROUTING {
        type nat hook postrouting priority 100; policy accept;
        counter jump VYOS_PRE_SNAT_HOOK
        oifname  {eth0} ip saddr  10.0.0.0/24  ip daddr  @FQDN_nat_destination_100_d counter masquerade comment "SRC-NAT-100"

    }
    set FQDN_nat_source_100_d {
        type ipv4_addr
        flags interval
    }

    chain VYOS_PRE_DNAT_HOOK {
        return
    }

    chain VYOS_PRE_SNAT_HOOK {
        return
    }




}

nft check:

vyos@r14# sudo nft -c -f /run/nftables_nat.conf 
/run/nftables_nat.conf:24:58-84: Error: No such file or directory; did you mean set ‘FQDN_nat_source_100_d’ in table ip ‘vyos_nat’?
        oifname  {eth0} ip saddr  10.0.0.0/24  ip daddr  @FQDN_nat_destination_100_d counter masquerade comment "SRC-NAT-100"
                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
[edit]
vyos@r14# 

Version:

vyos@r14# run ping google.com
PING google.com (216.58.208.206) 56(84) bytes of data.
64 bytes from par10s21-in-f206.1e100.net (216.58.208.206): icmp_seq=1 ttl=115 time=24.3 ms
^C
--- google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 24.316/24.316/24.316/0.000 ms
[edit]
vyos@r14# 
[edit]
vyos@r14# run show version 
Version:          VyOS 1.5-rolling-202409130007
Release train:    current
Release flavor:   generic

@@ -18,6 +18,7 @@
<help>NAT destination parameters</help>
</properties>
<children>
#include <include/firewall/fqdn.xml.i>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FQDN should be multi, isn't it?

vyos@r14# set nat source rule 100 destination fqdn example.com
[edit]
vyos@r14# set nat source rule 100 destination fqdn n1.example.com
[edit]
vyos@r14# set nat source rule 100 destination fqdn n2.example.com
[edit]
vyos@r14# set nat source rule 100 destination fqdn n3.example.com
[edit]
vyos@r14# show nat source rule 100 destination 
+fqdn n3.example.com
[edit]
vyos@r14# 

one FQDN per rule is inconvenient

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should steer users to use a group for multiple per rule.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, this is analogous to the firewall syntax, which supports either a group (including a domain group) or a single FQDN. Domain groups are supported in NAT.

@nicolas-fort
Copy link
Contributor Author

Fails:

vyos@r14# compare 
+ nat {
+     source {
+         rule 100 {
+             destination {
+                 fqdn "google.com"
+             }
+             outbound-interface {
+                 name "eth0"
+             }
+             source {
+                 address "10.0.0.0/24"
+             }
+             translation {
+                 address "masquerade"
+             }
+         }
+     }
+ }

[edit]
vyos@r14# commit

Configuration file errors encountered!

[[nat]] failed
Commit failed
[edit]
vyos@r14# 

cat /run/nftables_nat.conf

#!/usr/sbin/nft -f


delete table ip vyos_nat
table ip vyos_nat {
    #
    # Destination NAT rules build up here
    #
    chain PREROUTING {
        type nat hook prerouting priority -100; policy accept;
        counter jump VYOS_PRE_DNAT_HOOK
    }
    set FQDN_nat_source_100_d {
        type ipv4_addr
        flags interval
    }

    #
    # Source NAT rules build up here
    #
    chain POSTROUTING {
        type nat hook postrouting priority 100; policy accept;
        counter jump VYOS_PRE_SNAT_HOOK
        oifname  {eth0} ip saddr  10.0.0.0/24  ip daddr  @FQDN_nat_destination_100_d counter masquerade comment "SRC-NAT-100"

    }
    set FQDN_nat_source_100_d {
        type ipv4_addr
        flags interval
    }

    chain VYOS_PRE_DNAT_HOOK {
        return
    }

    chain VYOS_PRE_SNAT_HOOK {
        return
    }




}

nft check:

vyos@r14# sudo nft -c -f /run/nftables_nat.conf 
/run/nftables_nat.conf:24:58-84: Error: No such file or directory; did you mean set ‘FQDN_nat_source_100_d’ in table ip ‘vyos_nat’?
        oifname  {eth0} ip saddr  10.0.0.0/24  ip daddr  @FQDN_nat_destination_100_d counter masquerade comment "SRC-NAT-100"
                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
[edit]
vyos@r14# 

Version:

vyos@r14# run ping google.com
PING google.com (216.58.208.206) 56(84) bytes of data.
64 bytes from par10s21-in-f206.1e100.net (216.58.208.206): icmp_seq=1 ttl=115 time=24.3 ms
^C
--- google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 24.316/24.316/24.316/0.000 ms
[edit]
vyos@r14# 
[edit]
vyos@r14# run show version 
Version:          VyOS 1.5-rolling-202409130007
Release train:    current
Release flavor:   generic

Fixed:

vyos@fqdn-nat# compare commands 
set nat source rule 100 destination fqdn 'google.com'
set nat source rule 100 outbound-interface name 'eth0'
set nat source rule 100 source address '10.0.0.0/24'
set nat source rule 100 translation address 'masquerade'

[edit]
vyos@fqdn-nat# commit
[edit]
vyos@fqdn-nat#

And:

vyos@fqdn-nat# sudo nft list table ip vyos_nat
table ip vyos_nat {
        set FQDN_nat_source_100_d {
                type ipv4_addr
                flags interval
                elements = { 142.250.79.142 }
        }

        chain PREROUTING {
                type nat hook prerouting priority dstnat; policy accept;
                counter packets 4 bytes 990 jump VYOS_PRE_DNAT_HOOK
        }

        chain POSTROUTING {
                type nat hook postrouting priority srcnat; policy accept;
                counter packets 5 bytes 337 jump VYOS_PRE_SNAT_HOOK
                oifname "eth0" ip saddr 10.0.0.0/24 ip daddr @FQDN_nat_source_100_d counter packets 0 bytes 0 masquerade comment "SRC-NAT-100"
        }

        chain VYOS_PRE_DNAT_HOOK {
                return
        }

        chain VYOS_PRE_SNAT_HOOK {
                return
        }
}
[edit]
vyos@fqdn-nat# 

I've also added an extra entry in smoketests

@@ -18,6 +18,7 @@
<help>NAT destination parameters</help>
</properties>
<children>
#include <include/firewall/fqdn.xml.i>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, this is analogous to the firewall syntax, which supports either a group (including a domain group) or a single FQDN. Domain groups are supported in NAT.

Copy link
Member

@sarthurdev sarthurdev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to approve this, sorry it's taken so long.

Only comments are that I'm not a fan of the use of the temporary file in /run for other conf scripts to pick up as a "signal". But agree there isn't really a clean/performant solution for this at the moment (I'm talking to John about how we should best go about it).

@dmbaturin dmbaturin dismissed c-po’s stale review September 30, 2024 14:48

Issues already addressed

@dmbaturin dmbaturin merged commit eb55965 into vyos:current Sep 30, 2024
14 of 17 checks passed
@dmbaturin
Copy link
Member

@Mergifyio backport circinus

Copy link
Contributor

mergify bot commented Sep 30, 2024

backport circinus

✅ Backports have been created

c-po added a commit that referenced this pull request Sep 30, 2024
T6687: add fqdn support to nat rules. (backport #4024)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

5 participants