summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/package-smoketest.yml5
-rw-r--r--Jenkinsfile23
-rw-r--r--data/templates/firewall/nftables-nat.j213
-rw-r--r--data/templates/node_exporter/node_exporter.service.j220
-rw-r--r--data/templates/ocserv/radius_conf.j22
-rw-r--r--debian/vyos-1x.install1
-rw-r--r--debian/vyos-1x.postinst5
-rw-r--r--interface-definitions/include/firewall/bridge-hook-forward.xml.i6
-rw-r--r--interface-definitions/include/firewall/bridge-hook-output.xml.i6
-rw-r--r--interface-definitions/include/firewall/bridge-hook-prerouting.xml.i5
-rw-r--r--interface-definitions/include/firewall/ipv4-custom-name.xml.i6
-rw-r--r--interface-definitions/include/firewall/ipv4-hook-forward.xml.i5
-rw-r--r--interface-definitions/include/firewall/ipv4-hook-output.xml.i10
-rw-r--r--interface-definitions/include/firewall/ipv4-hook-prerouting.xml.i4
-rw-r--r--interface-definitions/include/firewall/ipv6-custom-name.xml.i5
-rw-r--r--interface-definitions/include/firewall/ipv6-hook-forward.xml.i5
-rw-r--r--interface-definitions/include/firewall/ipv6-hook-output.xml.i10
-rw-r--r--interface-definitions/include/firewall/ipv6-hook-prerouting.xml.i4
-rw-r--r--interface-definitions/include/firewall/set-packet-modifications-conn-mark.xml.i21
-rw-r--r--interface-definitions/include/firewall/set-packet-modifications-dscp.xml.i21
-rwxr-xr-xinterface-definitions/include/firewall/set-packet-modifications-hop-limit.xml.i21
-rw-r--r--interface-definitions/include/firewall/set-packet-modifications-mark.xml.i21
-rw-r--r--interface-definitions/include/firewall/set-packet-modifications-table-and-vrf.xml.i48
-rw-r--r--interface-definitions/include/firewall/set-packet-modifications-tcp-mss.xml.i21
-rwxr-xr-xinterface-definitions/include/firewall/set-packet-modifications-ttl.xml.i21
-rw-r--r--interface-definitions/include/firewall/set-packet-modifications.xml.i96
-rw-r--r--interface-definitions/include/nat-rule.xml.i2
-rw-r--r--interface-definitions/include/policy/route-common.xml.i6
-rw-r--r--interface-definitions/policy.xml.in48
-rw-r--r--interface-definitions/service_monitoring_node_exporter.xml.in25
-rw-r--r--python/vyos/configtree.py36
-rwxr-xr-xpython/vyos/firewall.py53
-rw-r--r--python/vyos/nat.py7
-rwxr-xr-xsmoketest/scripts/cli/test_firewall.py16
-rwxr-xr-xsmoketest/scripts/cli/test_nat.py26
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_ospf.py17
-rwxr-xr-xsmoketest/scripts/cli/test_service_monitoring_node-exporter.py64
-rwxr-xr-xsmoketest/scripts/cli/test_vpn_ipsec.py8
-rwxr-xr-xsrc/conf_mode/firewall.py21
-rwxr-xr-xsrc/conf_mode/nat.py20
-rwxr-xr-xsrc/conf_mode/service_monitoring_node-exporter.py101
-rwxr-xr-xsrc/conf_mode/vpn_ipsec.py13
-rwxr-xr-xsrc/helpers/vyos-domain-resolver.py107
-rw-r--r--src/systemd/vyos-domain-resolver.service1
-rwxr-xr-xsrc/utils/vyos-show-config57
-rwxr-xr-xsrc/validators/ipv4-range42
-rwxr-xr-xsrc/validators/ipv6-range26
47 files changed, 839 insertions, 262 deletions
diff --git a/.github/workflows/package-smoketest.yml b/.github/workflows/package-smoketest.yml
index a74c35adf..3595bcf0e 100644
--- a/.github/workflows/package-smoketest.yml
+++ b/.github/workflows/package-smoketest.yml
@@ -1,7 +1,7 @@
name: VyOS ISO integration Test
on:
- pull_request:
+ pull_request_target:
branches:
- current
paths:
@@ -17,7 +17,7 @@ env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed for PR comments
BUILD_BY: autobuild@vyos.net
DEBIAN_MIRROR: http://deb.debian.org/debian/
- VYOS_MIRROR: https://rolling-packages.vyos.net/current/
+ VYOS_MIRROR: https://packages.vyos.net/repositories/current/
jobs:
build_iso:
@@ -39,6 +39,7 @@ jobs:
path: packages/vyos-1x
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
+ repository: ${{ github.event.pull_request.head.repo.full_name }}
- name: Build vyos-1x package
run: |
cd packages/vyos-1x; dpkg-buildpackage -uc -us -tc -b
diff --git a/Jenkinsfile b/Jenkinsfile
deleted file mode 100644
index 21a6829c0..000000000
--- a/Jenkinsfile
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (C) 2020-2021 VyOS maintainers and contributors
-//
-// This program is free software; you can redistribute it and/or modify
-// in order to easy exprort images built to "external" world
-// it under the terms of the GNU General Public License version 2 or later as
-// published by the Free Software Foundation.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-@NonCPS
-
-// Using a version specifier library, use 'current' branch. The underscore (_)
-// is not a typo! You need this underscore if the line immediately after the
-// @Library annotation is not an import statement!
-@Library('vyos-build@current')_
-
-// Start package build using library function from https://github.com/vyos/vyos-build
-buildPackage(null, null, null, true)
diff --git a/data/templates/firewall/nftables-nat.j2 b/data/templates/firewall/nftables-nat.j2
index 4254f6a0e..8c8dd3a8b 100644
--- a/data/templates/firewall/nftables-nat.j2
+++ b/data/templates/firewall/nftables-nat.j2
@@ -19,6 +19,12 @@ table ip vyos_nat {
{% endfor %}
{% endif %}
}
+{% for set_name in ip_fqdn %}
+ set FQDN_nat_{{ set_name }} {
+ type ipv4_addr
+ flags interval
+ }
+{% endfor %}
#
# Source NAT rules build up here
@@ -31,7 +37,14 @@ table ip vyos_nat {
{{ config | nat_rule(rule, 'source') }}
{% endfor %}
{% endif %}
+
+ }
+{% for set_name in ip_fqdn %}
+ set FQDN_nat_{{ set_name }} {
+ type ipv4_addr
+ flags interval
}
+{% endfor %}
chain VYOS_PRE_DNAT_HOOK {
return
diff --git a/data/templates/node_exporter/node_exporter.service.j2 b/data/templates/node_exporter/node_exporter.service.j2
new file mode 100644
index 000000000..62e7e6774
--- /dev/null
+++ b/data/templates/node_exporter/node_exporter.service.j2
@@ -0,0 +1,20 @@
+{% set vrf_command = 'ip vrf exec ' ~ vrf ~ ' runuser -u node_exporter -- ' if vrf is vyos_defined else '' %}
+[Unit]
+Description=Node Exporter
+Documentation=https://github.com/prometheus/node_exporter
+After=network.target
+
+[Service]
+{% if vrf is not vyos_defined %}
+User=node_exporter
+{% endif %}
+ExecStart={{ vrf_command }}/usr/sbin/node_exporter \
+{% if listen_address is vyos_defined %}
+{% for address in listen_address %}
+ --web.listen-address={{ address }}:{{ port }}
+{% endfor %}
+{% else %}
+ --web.listen-address=:{{ port }}
+{% endif %}
+[Install]
+WantedBy=multi-user.target
diff --git a/data/templates/ocserv/radius_conf.j2 b/data/templates/ocserv/radius_conf.j2
index 1ab322f69..c86929e47 100644
--- a/data/templates/ocserv/radius_conf.j2
+++ b/data/templates/ocserv/radius_conf.j2
@@ -22,7 +22,7 @@ authserver {{ authsrv }}
{% endif %}
{% endfor %}
radius_timeout {{ authentication['radius']['timeout'] }}
-{% if source_address %}
+{% if authentication.radius.source_address is vyos_defined %}
bindaddr {{ authentication['radius']['source_address'] }}
{% else %}
bindaddr *
diff --git a/debian/vyos-1x.install b/debian/vyos-1x.install
index 7171911dc..fff6ebeab 100644
--- a/debian/vyos-1x.install
+++ b/debian/vyos-1x.install
@@ -25,6 +25,7 @@ srv/localui
usr/sbin
usr/bin/config-mgmt
usr/bin/initial-setup
+usr/bin/vyos-show-config
usr/bin/vyos-config-file-query
usr/bin/vyos-config-to-commands
usr/bin/vyos-config-to-json
diff --git a/debian/vyos-1x.postinst b/debian/vyos-1x.postinst
index dc8ada267..d83634cfc 100644
--- a/debian/vyos-1x.postinst
+++ b/debian/vyos-1x.postinst
@@ -21,6 +21,11 @@ if ! grep -q '^openvpn' /etc/passwd; then
adduser --quiet --firstuid 100 --system --group --shell /usr/sbin/nologin openvpn
fi
+# node_exporter should get its own user
+if ! grep -q '^node_exporter' /etc/passwd; then
+ adduser --quiet --firstuid 100 --system --group --shell /bin/false node_exporter
+fi
+
# We need to have a group for RADIUS service users to use it inside PAM rules
if ! grep -q '^radius' /etc/group; then
addgroup --firstgid 1000 --quiet radius
diff --git a/interface-definitions/include/firewall/bridge-hook-forward.xml.i b/interface-definitions/include/firewall/bridge-hook-forward.xml.i
index fcc981925..03ac26cf6 100644
--- a/interface-definitions/include/firewall/bridge-hook-forward.xml.i
+++ b/interface-definitions/include/firewall/bridge-hook-forward.xml.i
@@ -32,6 +32,12 @@
#include <include/firewall/state.xml.i>
#include <include/firewall/inbound-interface.xml.i>
#include <include/firewall/outbound-interface.xml.i>
+ #include <include/firewall/set-packet-modifications-dscp.xml.i>
+ #include <include/firewall/set-packet-modifications-conn-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-tcp-mss.xml.i>
+ #include <include/firewall/set-packet-modifications-ttl.xml.i>
+ #include <include/firewall/set-packet-modifications-hop-limit.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/include/firewall/bridge-hook-output.xml.i b/interface-definitions/include/firewall/bridge-hook-output.xml.i
index 38b8b08ca..853315989 100644
--- a/interface-definitions/include/firewall/bridge-hook-output.xml.i
+++ b/interface-definitions/include/firewall/bridge-hook-output.xml.i
@@ -31,6 +31,12 @@
#include <include/firewall/connection-status.xml.i>
#include <include/firewall/state.xml.i>
#include <include/firewall/outbound-interface.xml.i>
+ #include <include/firewall/set-packet-modifications-dscp.xml.i>
+ #include <include/firewall/set-packet-modifications-conn-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-tcp-mss.xml.i>
+ #include <include/firewall/set-packet-modifications-ttl.xml.i>
+ #include <include/firewall/set-packet-modifications-hop-limit.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/include/firewall/bridge-hook-prerouting.xml.i b/interface-definitions/include/firewall/bridge-hook-prerouting.xml.i
index ea567644f..7a45f5cd1 100644
--- a/interface-definitions/include/firewall/bridge-hook-prerouting.xml.i
+++ b/interface-definitions/include/firewall/bridge-hook-prerouting.xml.i
@@ -28,6 +28,11 @@
#include <include/firewall/common-rule-bridge.xml.i>
#include <include/firewall/action-and-notrack.xml.i>
#include <include/firewall/inbound-interface.xml.i>
+ #include <include/firewall/set-packet-modifications-dscp.xml.i>
+ #include <include/firewall/set-packet-modifications-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-tcp-mss.xml.i>
+ #include <include/firewall/set-packet-modifications-ttl.xml.i>
+ #include <include/firewall/set-packet-modifications-hop-limit.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/include/firewall/ipv4-custom-name.xml.i b/interface-definitions/include/firewall/ipv4-custom-name.xml.i
index 8046b2d6c..b08262e2d 100644
--- a/interface-definitions/include/firewall/ipv4-custom-name.xml.i
+++ b/interface-definitions/include/firewall/ipv4-custom-name.xml.i
@@ -36,6 +36,12 @@
#include <include/firewall/match-ipsec.xml.i>
#include <include/firewall/offload-target.xml.i>
#include <include/firewall/outbound-interface.xml.i>
+ #include <include/firewall/set-packet-modifications-dscp.xml.i>
+ #include <include/firewall/set-packet-modifications-conn-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-tcp-mss.xml.i>
+ #include <include/firewall/set-packet-modifications-ttl.xml.i>
+
</children>
</tagNode>
</children>
diff --git a/interface-definitions/include/firewall/ipv4-hook-forward.xml.i b/interface-definitions/include/firewall/ipv4-hook-forward.xml.i
index b0e240a03..a2da4b701 100644
--- a/interface-definitions/include/firewall/ipv4-hook-forward.xml.i
+++ b/interface-definitions/include/firewall/ipv4-hook-forward.xml.i
@@ -31,6 +31,11 @@
#include <include/firewall/match-ipsec.xml.i>
#include <include/firewall/offload-target.xml.i>
#include <include/firewall/outbound-interface.xml.i>
+ #include <include/firewall/set-packet-modifications-dscp.xml.i>
+ #include <include/firewall/set-packet-modifications-conn-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-tcp-mss.xml.i>
+ #include <include/firewall/set-packet-modifications-ttl.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/include/firewall/ipv4-hook-output.xml.i b/interface-definitions/include/firewall/ipv4-hook-output.xml.i
index ee9157592..f68136557 100644
--- a/interface-definitions/include/firewall/ipv4-hook-output.xml.i
+++ b/interface-definitions/include/firewall/ipv4-hook-output.xml.i
@@ -28,6 +28,11 @@
#include <include/firewall/common-rule-ipv4.xml.i>
#include <include/firewall/match-ipsec-out.xml.i>
#include <include/firewall/outbound-interface.xml.i>
+ #include <include/firewall/set-packet-modifications-dscp.xml.i>
+ #include <include/firewall/set-packet-modifications-conn-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-tcp-mss.xml.i>
+ #include <include/firewall/set-packet-modifications-ttl.xml.i>
</children>
</tagNode>
</children>
@@ -56,6 +61,11 @@
#include <include/firewall/common-rule-ipv4-raw.xml.i>
#include <include/firewall/match-ipsec-out.xml.i>
#include <include/firewall/outbound-interface.xml.i>
+ #include <include/firewall/set-packet-modifications-dscp.xml.i>
+ #include <include/firewall/set-packet-modifications-conn-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-tcp-mss.xml.i>
+ #include <include/firewall/set-packet-modifications-ttl.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/include/firewall/ipv4-hook-prerouting.xml.i b/interface-definitions/include/firewall/ipv4-hook-prerouting.xml.i
index b431303ae..6f9fe6842 100644
--- a/interface-definitions/include/firewall/ipv4-hook-prerouting.xml.i
+++ b/interface-definitions/include/firewall/ipv4-hook-prerouting.xml.i
@@ -35,6 +35,10 @@
#include <include/firewall/common-rule-ipv4-raw.xml.i>
#include <include/firewall/match-ipsec-in.xml.i>
#include <include/firewall/inbound-interface.xml.i>
+ #include <include/firewall/set-packet-modifications-dscp.xml.i>
+ #include <include/firewall/set-packet-modifications-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-tcp-mss.xml.i>
+ #include <include/firewall/set-packet-modifications-ttl.xml.i>
<leafNode name="jump-target">
<properties>
<help>Set jump target. Action jump must be defined to use this setting</help>
diff --git a/interface-definitions/include/firewall/ipv6-custom-name.xml.i b/interface-definitions/include/firewall/ipv6-custom-name.xml.i
index fb8740c38..d49267b52 100644
--- a/interface-definitions/include/firewall/ipv6-custom-name.xml.i
+++ b/interface-definitions/include/firewall/ipv6-custom-name.xml.i
@@ -36,6 +36,11 @@
#include <include/firewall/match-ipsec.xml.i>
#include <include/firewall/offload-target.xml.i>
#include <include/firewall/outbound-interface.xml.i>
+ #include <include/firewall/set-packet-modifications-dscp.xml.i>
+ #include <include/firewall/set-packet-modifications-conn-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-tcp-mss.xml.i>
+ #include <include/firewall/set-packet-modifications-hop-limit.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/include/firewall/ipv6-hook-forward.xml.i b/interface-definitions/include/firewall/ipv6-hook-forward.xml.i
index 7efc2614e..79898d691 100644
--- a/interface-definitions/include/firewall/ipv6-hook-forward.xml.i
+++ b/interface-definitions/include/firewall/ipv6-hook-forward.xml.i
@@ -31,6 +31,11 @@
#include <include/firewall/match-ipsec.xml.i>
#include <include/firewall/offload-target.xml.i>
#include <include/firewall/outbound-interface.xml.i>
+ #include <include/firewall/set-packet-modifications-dscp.xml.i>
+ #include <include/firewall/set-packet-modifications-conn-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-tcp-mss.xml.i>
+ #include <include/firewall/set-packet-modifications-hop-limit.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/include/firewall/ipv6-hook-output.xml.i b/interface-definitions/include/firewall/ipv6-hook-output.xml.i
index d3c4c1ead..9a6d0bb77 100644
--- a/interface-definitions/include/firewall/ipv6-hook-output.xml.i
+++ b/interface-definitions/include/firewall/ipv6-hook-output.xml.i
@@ -28,6 +28,11 @@
#include <include/firewall/common-rule-ipv6.xml.i>
#include <include/firewall/match-ipsec-out.xml.i>
#include <include/firewall/outbound-interface.xml.i>
+ #include <include/firewall/set-packet-modifications-dscp.xml.i>
+ #include <include/firewall/set-packet-modifications-conn-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-tcp-mss.xml.i>
+ #include <include/firewall/set-packet-modifications-hop-limit.xml.i>
</children>
</tagNode>
</children>
@@ -56,6 +61,11 @@
#include <include/firewall/common-rule-ipv6-raw.xml.i>
#include <include/firewall/match-ipsec-out.xml.i>
#include <include/firewall/outbound-interface.xml.i>
+ #include <include/firewall/set-packet-modifications-dscp.xml.i>
+ #include <include/firewall/set-packet-modifications-conn-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-tcp-mss.xml.i>
+ #include <include/firewall/set-packet-modifications-hop-limit.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/include/firewall/ipv6-hook-prerouting.xml.i b/interface-definitions/include/firewall/ipv6-hook-prerouting.xml.i
index 21f8de6f9..15454bbbf 100644
--- a/interface-definitions/include/firewall/ipv6-hook-prerouting.xml.i
+++ b/interface-definitions/include/firewall/ipv6-hook-prerouting.xml.i
@@ -35,6 +35,10 @@
#include <include/firewall/common-rule-ipv6-raw.xml.i>
#include <include/firewall/match-ipsec-in.xml.i>
#include <include/firewall/inbound-interface.xml.i>
+ #include <include/firewall/set-packet-modifications-dscp.xml.i>
+ #include <include/firewall/set-packet-modifications-mark.xml.i>
+ #include <include/firewall/set-packet-modifications-tcp-mss.xml.i>
+ #include <include/firewall/set-packet-modifications-hop-limit.xml.i>
<leafNode name="jump-target">
<properties>
<help>Set jump target. Action jump must be defined to use this setting</help>
diff --git a/interface-definitions/include/firewall/set-packet-modifications-conn-mark.xml.i b/interface-definitions/include/firewall/set-packet-modifications-conn-mark.xml.i
new file mode 100644
index 000000000..dff95d324
--- /dev/null
+++ b/interface-definitions/include/firewall/set-packet-modifications-conn-mark.xml.i
@@ -0,0 +1,21 @@
+<!-- include start from firewall/set-packet-modifications-conn-mark.xml.i -->
+<node name="set">
+ <properties>
+ <help>Packet modifications</help>
+ </properties>
+ <children>
+ <leafNode name="connection-mark">
+ <properties>
+ <help>Set connection mark</help>
+ <valueHelp>
+ <format>u32:0-2147483647</format>
+ <description>Connection mark</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-2147483647"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/firewall/set-packet-modifications-dscp.xml.i b/interface-definitions/include/firewall/set-packet-modifications-dscp.xml.i
new file mode 100644
index 000000000..5082806fb
--- /dev/null
+++ b/interface-definitions/include/firewall/set-packet-modifications-dscp.xml.i
@@ -0,0 +1,21 @@
+<!-- include start from firewall/set-packet-modifications-dscp.xml.i -->
+<node name="set">
+ <properties>
+ <help>Packet modifications</help>
+ </properties>
+ <children>
+ <leafNode name="dscp">
+ <properties>
+ <help>Set DSCP (Packet Differentiated Services Codepoint) bits</help>
+ <valueHelp>
+ <format>u32:0-63</format>
+ <description>DSCP number</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-63"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/firewall/set-packet-modifications-hop-limit.xml.i b/interface-definitions/include/firewall/set-packet-modifications-hop-limit.xml.i
new file mode 100755
index 000000000..8a6e5347a
--- /dev/null
+++ b/interface-definitions/include/firewall/set-packet-modifications-hop-limit.xml.i
@@ -0,0 +1,21 @@
+<!-- include start from firewall/set-packet-modifications-hop-limit.xml.i -->
+<node name="set">
+ <properties>
+ <help>Packet modifications</help>
+ </properties>
+ <children>
+ <leafNode name="hop-limit">
+ <properties>
+ <help>Set hop limit</help>
+ <valueHelp>
+ <format>u32:0-255</format>
+ <description>Hop limit number</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/firewall/set-packet-modifications-mark.xml.i b/interface-definitions/include/firewall/set-packet-modifications-mark.xml.i
new file mode 100644
index 000000000..b229d0579
--- /dev/null
+++ b/interface-definitions/include/firewall/set-packet-modifications-mark.xml.i
@@ -0,0 +1,21 @@
+<!-- include start from firewall/set-packet-modifications-mark.xml.i -->
+<node name="set">
+ <properties>
+ <help>Packet modifications</help>
+ </properties>
+ <children>
+ <leafNode name="mark">
+ <properties>
+ <help>Set packet mark</help>
+ <valueHelp>
+ <format>u32:1-2147483647</format>
+ <description>Packet mark</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-2147483647"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/firewall/set-packet-modifications-table-and-vrf.xml.i b/interface-definitions/include/firewall/set-packet-modifications-table-and-vrf.xml.i
new file mode 100644
index 000000000..c7875b31d
--- /dev/null
+++ b/interface-definitions/include/firewall/set-packet-modifications-table-and-vrf.xml.i
@@ -0,0 +1,48 @@
+<!-- include start from firewall/set-packet-modifications-table-and-vrf.xml.i -->
+<node name="set">
+ <properties>
+ <help>Packet modifications</help>
+ </properties>
+ <children>
+ <leafNode name="table">
+ <properties>
+ <help>Set the routing table for matched packets</help>
+ <valueHelp>
+ <format>u32:1-200</format>
+ <description>Table number</description>
+ </valueHelp>
+ <valueHelp>
+ <format>main</format>
+ <description>Main table</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-200"/>
+ <regex>(main)</regex>
+ </constraint>
+ <completionHelp>
+ <list>main</list>
+ <path>protocols static table</path>
+ </completionHelp>
+ </properties>
+ </leafNode>
+ <leafNode name="vrf">
+ <properties>
+ <help>VRF to forward packet with</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>VRF instance name</description>
+ </valueHelp>
+ <valueHelp>
+ <format>default</format>
+ <description>Forward into default global VRF</description>
+ </valueHelp>
+ <completionHelp>
+ <list>default</list>
+ <path>vrf name</path>
+ </completionHelp>
+ #include <include/constraint/vrf.xml.i>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/firewall/set-packet-modifications-tcp-mss.xml.i b/interface-definitions/include/firewall/set-packet-modifications-tcp-mss.xml.i
new file mode 100644
index 000000000..06ffdfede
--- /dev/null
+++ b/interface-definitions/include/firewall/set-packet-modifications-tcp-mss.xml.i
@@ -0,0 +1,21 @@
+<!-- include start from firewall/set-packet-modifications-tcp-mss.xml.i -->
+<node name="set">
+ <properties>
+ <help>Packet modifications</help>
+ </properties>
+ <children>
+ <leafNode name="tcp-mss">
+ <properties>
+ <help>Set TCP Maximum Segment Size</help>
+ <valueHelp>
+ <format>u32:500-1460</format>
+ <description>Explicitly set TCP MSS value</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 500-1460"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/firewall/set-packet-modifications-ttl.xml.i b/interface-definitions/include/firewall/set-packet-modifications-ttl.xml.i
new file mode 100755
index 000000000..e2f14050b
--- /dev/null
+++ b/interface-definitions/include/firewall/set-packet-modifications-ttl.xml.i
@@ -0,0 +1,21 @@
+<!-- include start from firewall/set-packet-modifications-ttl.xml.i -->
+<node name="set">
+ <properties>
+ <help>Packet modifications</help>
+ </properties>
+ <children>
+ <leafNode name="ttl">
+ <properties>
+ <help>Set TTL (time to live)</help>
+ <valueHelp>
+ <format>u32:0-255</format>
+ <description>TTL number</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/firewall/set-packet-modifications.xml.i b/interface-definitions/include/firewall/set-packet-modifications.xml.i
deleted file mode 100644
index ee019b64e..000000000
--- a/interface-definitions/include/firewall/set-packet-modifications.xml.i
+++ /dev/null
@@ -1,96 +0,0 @@
-<!-- include start from firewall/set-packet-modifications.xml.i -->
-<node name="set">
- <properties>
- <help>Packet modifications</help>
- </properties>
- <children>
- <leafNode name="connection-mark">
- <properties>
- <help>Set connection mark</help>
- <valueHelp>
- <format>u32:0-2147483647</format>
- <description>Connection mark</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-2147483647"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="dscp">
- <properties>
- <help>Set DSCP (Packet Differentiated Services Codepoint) bits</help>
- <valueHelp>
- <format>u32:0-63</format>
- <description>DSCP number</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-63"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="mark">
- <properties>
- <help>Set packet mark</help>
- <valueHelp>
- <format>u32:1-2147483647</format>
- <description>Packet mark</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-2147483647"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="table">
- <properties>
- <help>Set the routing table for matched packets</help>
- <valueHelp>
- <format>u32:1-200</format>
- <description>Table number</description>
- </valueHelp>
- <valueHelp>
- <format>main</format>
- <description>Main table</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-200"/>
- <regex>(main)</regex>
- </constraint>
- <completionHelp>
- <list>main</list>
- <path>protocols static table</path>
- </completionHelp>
- </properties>
- </leafNode>
- <leafNode name="vrf">
- <properties>
- <help>VRF to forward packet with</help>
- <valueHelp>
- <format>txt</format>
- <description>VRF instance name</description>
- </valueHelp>
- <valueHelp>
- <format>default</format>
- <description>Forward into default global VRF</description>
- </valueHelp>
- <completionHelp>
- <list>default</list>
- <path>vrf name</path>
- </completionHelp>
- #include <include/constraint/vrf.xml.i>
- </properties>
- </leafNode>
- <leafNode name="tcp-mss">
- <properties>
- <help>Set TCP Maximum Segment Size</help>
- <valueHelp>
- <format>u32:500-1460</format>
- <description>Explicitly set TCP MSS value</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 500-1460"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
-</node>
-<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/nat-rule.xml.i b/interface-definitions/include/nat-rule.xml.i
index deb13529d..0a7179ff1 100644
--- a/interface-definitions/include/nat-rule.xml.i
+++ b/interface-definitions/include/nat-rule.xml.i
@@ -18,6 +18,7 @@
<help>NAT destination parameters</help>
</properties>
<children>
+ #include <include/firewall/fqdn.xml.i>
#include <include/nat-address.xml.i>
#include <include/nat-port.xml.i>
#include <include/firewall/source-destination-group.xml.i>
@@ -315,6 +316,7 @@
<help>NAT source parameters</help>
</properties>
<children>
+ #include <include/firewall/fqdn.xml.i>
#include <include/nat-address.xml.i>
#include <include/nat-port.xml.i>
#include <include/firewall/source-destination-group.xml.i>
diff --git a/interface-definitions/include/policy/route-common.xml.i b/interface-definitions/include/policy/route-common.xml.i
index 19ffc0506..5c69a5279 100644
--- a/interface-definitions/include/policy/route-common.xml.i
+++ b/interface-definitions/include/policy/route-common.xml.i
@@ -66,7 +66,11 @@
</leafNode>
</children>
</node>
-#include <include/firewall/set-packet-modifications.xml.i>
+#include <include/firewall/set-packet-modifications-conn-mark.xml.i>
+#include <include/firewall/set-packet-modifications-dscp.xml.i>
+#include <include/firewall/set-packet-modifications-mark.xml.i>
+#include <include/firewall/set-packet-modifications-table-and-vrf.xml.i>
+#include <include/firewall/set-packet-modifications-tcp-mss.xml.i>
#include <include/firewall/state.xml.i>
#include <include/firewall/tcp-flags.xml.i>
#include <include/firewall/tcp-mss.xml.i>
diff --git a/interface-definitions/policy.xml.in b/interface-definitions/policy.xml.in
index eb907cb9e..cbab6173f 100644
--- a/interface-definitions/policy.xml.in
+++ b/interface-definitions/policy.xml.in
@@ -202,11 +202,11 @@
<properties>
<help>Regular expression to match against a community-list</help>
<completionHelp>
- <list>local-AS no-advertise no-export internet additive</list>
+ <list>local-AS no-advertise no-export internet graceful-shutdown accept-own-nexthop accept-own route-filter-translated-v4 route-filter-v4 route-filter-translated-v6 route-filter-v6 llgr-stale no-llgr blackhole no-peer additive</list>
</completionHelp>
<valueHelp>
<format>&lt;aa:nn&gt;</format>
- <description>Community number in AA:NN format</description>
+ <description>Community number in AA:NN format where AA and NN are (0-65535)</description>
</valueHelp>
<valueHelp>
<format>local-AS</format>
@@ -225,6 +225,50 @@
<description>Well-known communities value 0</description>
</valueHelp>
<valueHelp>
+ <format>graceful-shutdown</format>
+ <description>Well-known communities value GRACEFUL_SHUTDOWN 0xFFFF0000</description>
+ </valueHelp>
+ <valueHelp>
+ <format>accept-own-nexthop</format>
+ <description>Well-known communities value ACCEPT_OWN_NEXTHOP 0xFFFF0008</description>
+ </valueHelp>
+ <valueHelp>
+ <format>accept-own</format>
+ <description>Well-known communities value ACCEPT_OWN 0xFFFF0001 65535:1</description>
+ </valueHelp>
+ <valueHelp>
+ <format>route-filter-translated-v4</format>
+ <description>Well-known communities value ROUTE_FILTER_TRANSLATED_v4 0xFFFF0002 65535:2</description>
+ </valueHelp>
+ <valueHelp>
+ <format>route-filter-v4</format>
+ <description>Well-known communities value ROUTE_FILTER_v4 0xFFFF0003 65535:3</description>
+ </valueHelp>
+ <valueHelp>
+ <format>route-filter-translated-v6</format>
+ <description>Well-known communities value ROUTE_FILTER_TRANSLATED_v6 0xFFFF0004 65535:4</description>
+ </valueHelp>
+ <valueHelp>
+ <format>route-filter-v6</format>
+ <description>Well-known communities value ROUTE_FILTER_v6 0xFFFF0005 65535:5</description>
+ </valueHelp>
+ <valueHelp>
+ <format>llgr-stale</format>
+ <description>Well-known communities value LLGR_STALE 0xFFFF0006 65535:6</description>
+ </valueHelp>
+ <valueHelp>
+ <format>no-llgr</format>
+ <description>Well-known communities value NO_LLGR 0xFFFF0007 65535:7</description>
+ </valueHelp>
+ <valueHelp>
+ <format>blackhole</format>
+ <description>Well-known communities value BLACKHOLE 0xFFFF029A 65535:666</description>
+ </valueHelp>
+ <valueHelp>
+ <format>no-peer</format>
+ <description>Well-known communities value NOPEER 0xFFFFFF04 65535:65284</description>
+ </valueHelp>
+ <valueHelp>
<format>additive</format>
<description>New value is appended to the existing value</description>
</valueHelp>
diff --git a/interface-definitions/service_monitoring_node_exporter.xml.in b/interface-definitions/service_monitoring_node_exporter.xml.in
new file mode 100644
index 000000000..a11d2304f
--- /dev/null
+++ b/interface-definitions/service_monitoring_node_exporter.xml.in
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<interfaceDefinition>
+ <node name="service">
+ <children>
+ <node name="monitoring">
+ <children>
+ <node name="node-exporter" owner="${vyos_conf_scripts_dir}/service_monitoring_node-exporter.py">
+ <properties>
+ <help>Prometheus exporter for hardware and operating system metrics</help>
+ <priority>1280</priority>
+ </properties>
+ <children>
+ #include <include/listen-address.xml.i>
+ #include <include/port-number.xml.i>
+ <leafNode name="port">
+ <defaultValue>9100</defaultValue>
+ </leafNode>
+ #include <include/interface/vrf.xml.i>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+ </node>
+</interfaceDefinition>
diff --git a/python/vyos/configtree.py b/python/vyos/configtree.py
index bd77ab899..ee8ca8b83 100644
--- a/python/vyos/configtree.py
+++ b/python/vyos/configtree.py
@@ -88,6 +88,10 @@ class ConfigTree(object):
self.__to_json_ast.argtypes = [c_void_p]
self.__to_json_ast.restype = c_char_p
+ self.__create_node = self.__lib.create_node
+ self.__create_node.argtypes = [c_void_p, c_char_p]
+ self.__create_node.restype = c_int
+
self.__set_add_value = self.__lib.set_add_value
self.__set_add_value.argtypes = [c_void_p, c_char_p, c_char_p]
self.__set_add_value.restype = c_int
@@ -140,6 +144,14 @@ class ConfigTree(object):
self.__set_tag.argtypes = [c_void_p, c_char_p]
self.__set_tag.restype = c_int
+ self.__is_leaf = self.__lib.is_leaf
+ self.__is_leaf.argtypes = [c_void_p, c_char_p]
+ self.__is_leaf.restype = c_bool
+
+ self.__set_leaf = self.__lib.set_leaf
+ self.__set_leaf.argtypes = [c_void_p, c_char_p, c_bool]
+ self.__set_leaf.restype = c_int
+
self.__get_subtree = self.__lib.get_subtree
self.__get_subtree.argtypes = [c_void_p, c_char_p]
self.__get_subtree.restype = c_void_p
@@ -197,6 +209,14 @@ class ConfigTree(object):
def to_json_ast(self):
return self.__to_json_ast(self.__config).decode()
+ def create_node(self, path):
+ check_path(path)
+ path_str = " ".join(map(str, path)).encode()
+
+ res = self.__create_node(self.__config, path_str)
+ if (res != 0):
+ raise ConfigTreeError(f"Path already exists: {path}")
+
def set(self, path, value=None, replace=True):
"""Set new entry in VyOS configuration.
path: configuration path e.g. 'system dns forwarding listen-address'
@@ -349,6 +369,22 @@ class ConfigTree(object):
else:
raise ConfigTreeError("Path [{}] doesn't exist".format(path_str))
+ def is_leaf(self, path):
+ check_path(path)
+ path_str = " ".join(map(str, path)).encode()
+
+ return self.__is_leaf(self.__config, path_str)
+
+ def set_leaf(self, path, value):
+ check_path(path)
+ path_str = " ".join(map(str, path)).encode()
+
+ res = self.__set_leaf(self.__config, path_str, value)
+ if (res == 0):
+ return True
+ else:
+ raise ConfigTreeError("Path [{}] doesn't exist".format(path_str))
+
def get_subtree(self, path, with_node=False):
check_path(path)
path_str = " ".join(map(str, path)).encode()
diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py
index 64fed8177..314e8dfe3 100755
--- a/python/vyos/firewall.py
+++ b/python/vyos/firewall.py
@@ -53,25 +53,32 @@ def conntrack_required(conf):
# Domain Resolver
-def fqdn_config_parse(firewall):
- firewall['ip_fqdn'] = {}
- firewall['ip6_fqdn'] = {}
-
- for domain, path in dict_search_recursive(firewall, 'fqdn'):
- hook_name = path[1]
- priority = path[2]
-
- fw_name = path[2]
- rule = path[4]
- suffix = path[5][0]
- set_name = f'{hook_name}_{priority}_{rule}_{suffix}'
-
- if (path[0] == 'ipv4') and (path[1] == 'forward' or path[1] == 'input' or path[1] == 'output' or path[1] == 'name'):
- firewall['ip_fqdn'][set_name] = domain
- elif (path[0] == 'ipv6') and (path[1] == 'forward' or path[1] == 'input' or path[1] == 'output' or path[1] == 'name'):
- if path[1] == 'name':
- set_name = f'name6_{priority}_{rule}_{suffix}'
- firewall['ip6_fqdn'][set_name] = domain
+def fqdn_config_parse(config, node):
+ config['ip_fqdn'] = {}
+ config['ip6_fqdn'] = {}
+
+ for domain, path in dict_search_recursive(config, 'fqdn'):
+ if node != 'nat':
+ hook_name = path[1]
+ priority = path[2]
+
+ rule = path[4]
+ suffix = path[5][0]
+ set_name = f'{hook_name}_{priority}_{rule}_{suffix}'
+
+ if (path[0] == 'ipv4') and (path[1] == 'forward' or path[1] == 'input' or path[1] == 'output' or path[1] == 'name'):
+ config['ip_fqdn'][set_name] = domain
+ elif (path[0] == 'ipv6') and (path[1] == 'forward' or path[1] == 'input' or path[1] == 'output' or path[1] == 'name'):
+ if path[1] == 'name':
+ set_name = f'name6_{priority}_{rule}_{suffix}'
+ config['ip6_fqdn'][set_name] = domain
+ else:
+ # Parse FQDN for NAT
+ nat_direction = path[0]
+ nat_rule = path[2]
+ suffix = path[3][0]
+ set_name = f'{nat_direction}_{nat_rule}_{suffix}'
+ config['ip_fqdn'][set_name] = domain
def fqdn_resolve(fqdn, ipv6=False):
try:
@@ -80,8 +87,6 @@ def fqdn_resolve(fqdn, ipv6=False):
except:
return None
-# End Domain Resolver
-
def find_nftables_rule(table, chain, rule_matches=[]):
# Find rule in table/chain that matches all criteria and return the handle
results = cmd(f'sudo nft --handle list chain {table} {chain}').split("\n")
@@ -578,6 +583,12 @@ def parse_rule(rule_conf, hook, fw_name, rule_id, ip_name):
if 'tcp_mss' in rule_conf['set']:
mss = rule_conf['set']['tcp_mss']
output.append(f'tcp option maxseg size set {mss}')
+ if 'ttl' in rule_conf['set']:
+ ttl = rule_conf['set']['ttl']
+ output.append(f'ip ttl set {ttl}')
+ if 'hop_limit' in rule_conf['set']:
+ hoplimit = rule_conf['set']['hop_limit']
+ output.append(f'ip6 hoplimit set {hoplimit}')
if 'action' in rule_conf:
if rule_conf['action'] == 'offload':
diff --git a/python/vyos/nat.py b/python/vyos/nat.py
index 5fab3c2a1..29f8e961b 100644
--- a/python/vyos/nat.py
+++ b/python/vyos/nat.py
@@ -242,6 +242,13 @@ def parse_nat_rule(rule_conf, rule_id, nat_type, ipv6=False):
output.append(f'{proto} {prefix}port {operator} @P_{group_name}')
+ if 'fqdn' in side_conf:
+ fqdn = side_conf['fqdn']
+ operator = ''
+ if fqdn[0] == '!':
+ operator = '!='
+ output.append(f' ip {prefix}addr {operator} @FQDN_nat_{nat_type}_{rule_id}_{prefix}')
+
output.append('counter')
if 'log' in rule_conf:
diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py
index 3e9ec2935..2d18f0495 100755
--- a/smoketest/scripts/cli/test_firewall.py
+++ b/smoketest/scripts/cli/test_firewall.py
@@ -248,6 +248,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.cli_set(['firewall', 'ipv4', 'prerouting', 'raw', 'rule', '1', 'action', 'notrack'])
self.cli_set(['firewall', 'ipv4', 'prerouting', 'raw', 'rule', '1', 'protocol', 'tcp'])
self.cli_set(['firewall', 'ipv4', 'prerouting', 'raw', 'rule', '1', 'destination', 'port', '23'])
+ self.cli_set(['firewall', 'ipv4', 'prerouting', 'raw', 'rule', '1', 'set', 'mark', '55'])
self.cli_commit()
@@ -275,7 +276,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
['OUT-raw default-action drop', 'drop'],
['chain VYOS_PREROUTING_raw'],
['type filter hook prerouting priority raw; policy accept;'],
- ['tcp dport 23', 'notrack'],
+ ['tcp dport 23', 'meta mark set 0x00000037', 'notrack'],
['PRE-raw default-action accept', 'accept'],
['chain NAME_smoketest'],
['saddr 172.16.20.10', 'daddr 172.16.10.10', 'log prefix "[ipv4-NAM-smoketest-1-A]" log level debug', 'ip ttl 15', 'accept'],
@@ -315,6 +316,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '1', 'mark', '1010'])
self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '1', 'action', 'jump'])
self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '1', 'jump-target', name])
+ self.cli_set(['firewall', 'ipv4', 'forward', 'filter', 'rule', '1', 'set', 'dscp', '32'])
self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'rule', '2', 'protocol', 'tcp'])
self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'rule', '2', 'mark', '!98765'])
@@ -331,7 +333,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
nftables_search = [
['chain VYOS_FORWARD_filter'],
['type filter hook forward priority filter; policy accept;'],
- ['ip saddr 198.51.100.1-198.51.100.50', 'meta mark 0x000003f2', f'jump NAME_{name}'],
+ ['ip saddr 198.51.100.1-198.51.100.50', 'meta mark 0x000003f2', 'ip dscp set cs4', f'jump NAME_{name}'],
['FWD-filter default-action drop', 'drop'],
['chain VYOS_INPUT_filter'],
['type filter hook input priority filter; policy accept;'],
@@ -485,6 +487,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.cli_set(['firewall', 'ipv6', 'prerouting', 'raw', 'rule', '1', 'action', 'drop'])
self.cli_set(['firewall', 'ipv6', 'prerouting', 'raw', 'rule', '1', 'protocol', 'tcp'])
self.cli_set(['firewall', 'ipv6', 'prerouting', 'raw', 'rule', '1', 'destination', 'port', '23'])
+ self.cli_set(['firewall', 'ipv6', 'prerouting', 'raw', 'rule', '1', 'set', 'hop-limit', '79'])
self.cli_commit()
@@ -507,7 +510,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
['OUT-raw default-action drop', 'drop'],
['chain VYOS_IPV6_PREROUTING_raw'],
['type filter hook prerouting priority raw; policy accept;'],
- ['tcp dport 23', 'drop'],
+ ['tcp dport 23', 'ip6 hoplimit set 79', 'drop'],
['PRE-raw default-action accept', 'accept'],
[f'chain NAME6_{name}'],
['saddr 2002::1-2002::10', 'daddr 2002::1:1', 'log prefix "[ipv6-NAM-v6-smoketest-1-A]" log level crit', 'accept'],
@@ -722,9 +725,12 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.cli_set(['firewall', 'bridge', 'forward', 'filter', 'rule', '1', 'action', 'accept'])
self.cli_set(['firewall', 'bridge', 'forward', 'filter', 'rule', '1', 'vlan', 'id', vlan_id])
self.cli_set(['firewall', 'bridge', 'forward', 'filter', 'rule', '1', 'vlan', 'ethernet-type', 'ipv4'])
+ self.cli_set(['firewall', 'bridge', 'forward', 'filter', 'rule', '1', 'set', 'connection-mark', '123123'])
+
self.cli_set(['firewall', 'bridge', 'forward', 'filter', 'rule', '2', 'action', 'jump'])
self.cli_set(['firewall', 'bridge', 'forward', 'filter', 'rule', '2', 'jump-target', name])
self.cli_set(['firewall', 'bridge', 'forward', 'filter', 'rule', '2', 'vlan', 'priority', vlan_prior])
+ self.cli_set(['firewall', 'bridge', 'forward', 'filter', 'rule', '2', 'set', 'ttl', '128'])
self.cli_set(['firewall', 'bridge', 'input', 'filter', 'rule', '1', 'action', 'accept'])
self.cli_set(['firewall', 'bridge', 'input', 'filter', 'rule', '1', 'inbound-interface', 'name', interface_in])
@@ -746,8 +752,8 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
['chain VYOS_FORWARD_filter'],
['type filter hook forward priority filter; policy accept;'],
['jump VYOS_STATE_POLICY'],
- [f'vlan id {vlan_id}', 'vlan type ip', 'accept'],
- [f'vlan pcp {vlan_prior}', f'jump NAME_{name}'],
+ [f'vlan id {vlan_id}', 'vlan type ip', 'ct mark set 0x0001e0f3', 'accept'],
+ [f'vlan pcp {vlan_prior}', 'ip ttl set 128', f'jump NAME_{name}'],
['log prefix "[bri-FWD-filter-default-D]"', 'drop', 'FWD-filter default-action drop'],
[f'chain NAME_{name}'],
[f'ether saddr {mac_address}', f'iifname "{interface_in}"', f'log prefix "[bri-NAM-{name}-1-A]" log level crit', 'accept'],
diff --git a/smoketest/scripts/cli/test_nat.py b/smoketest/scripts/cli/test_nat.py
index 5161e47fd..0beafcc6c 100755
--- a/smoketest/scripts/cli/test_nat.py
+++ b/smoketest/scripts/cli/test_nat.py
@@ -304,5 +304,31 @@ class TestNAT(VyOSUnitTestSHIM.TestCase):
self.verify_nftables(nftables_search, 'ip vyos_nat')
+ def test_nat_fqdn(self):
+ source_domain = 'vyos.dev'
+ destination_domain = 'vyos.io'
+
+ self.cli_set(src_path + ['rule', '1', 'outbound-interface', 'name', 'eth0'])
+ self.cli_set(src_path + ['rule', '1', 'source', 'fqdn', source_domain])
+ self.cli_set(src_path + ['rule', '1', 'translation', 'address', 'masquerade'])
+
+ self.cli_set(dst_path + ['rule', '1', 'destination', 'fqdn', destination_domain])
+ self.cli_set(dst_path + ['rule', '1', 'source', 'fqdn', source_domain])
+ self.cli_set(dst_path + ['rule', '1', 'destination', 'port', '5122'])
+ self.cli_set(dst_path + ['rule', '1', 'protocol', 'tcp'])
+ self.cli_set(dst_path + ['rule', '1', 'translation', 'address', '198.51.100.1'])
+ self.cli_set(dst_path + ['rule', '1', 'translation', 'port', '22'])
+
+
+ self.cli_commit()
+
+ nftables_search = [
+ ['set FQDN_nat_destination_1_d'],
+ ['set FQDN_nat_source_1_s'],
+ ['oifname "eth0"', 'ip saddr @FQDN_nat_source_1_s', 'masquerade', 'comment "SRC-NAT-1"'],
+ ['tcp dport 5122', 'ip saddr @FQDN_nat_destination_1_s', 'ip daddr @FQDN_nat_destination_1_d', 'dnat to 198.51.100.1:22', 'comment "DST-NAT-1"']
+ ]
+
+ self.verify_nftables(nftables_search, 'ip vyos_nat')
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py
index 905eaf2e9..c3ae54e12 100755
--- a/smoketest/scripts/cli/test_protocols_ospf.py
+++ b/smoketest/scripts/cli/test_protocols_ospf.py
@@ -15,6 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest
+import time
from base_vyostest_shim import VyOSUnitTestSHIM
@@ -558,6 +559,22 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase):
# Verify FRR ospfd configuration
frrconfig = self.getFRRconfig('router ospf', daemon=PROCESS_NAME)
+ # Required to prevent the race condition T6761
+ retry_count = 0
+ max_retries = 60
+
+ while not frrconfig and retry_count < max_retries:
+ # Log every 10 seconds
+ if retry_count % 10 == 0:
+ print(f"Attempt {retry_count}: FRR config is still empty. Retrying...")
+
+ retry_count += 1
+ time.sleep(1)
+ frrconfig = self.getFRRconfig('router ospf', daemon=PROCESS_NAME)
+
+ if not frrconfig:
+ print("Failed to retrieve FRR config after 60 seconds")
+
self.assertIn(f'router ospf', frrconfig)
self.assertIn(f' network {network} area {area1}', frrconfig)
diff --git a/smoketest/scripts/cli/test_service_monitoring_node-exporter.py b/smoketest/scripts/cli/test_service_monitoring_node-exporter.py
new file mode 100755
index 000000000..e18a3f7a2
--- /dev/null
+++ b/smoketest/scripts/cli/test_service_monitoring_node-exporter.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import unittest
+
+from base_vyostest_shim import VyOSUnitTestSHIM
+from vyos.utils.process import process_named_running
+from vyos.utils.file import read_file
+
+PROCESS_NAME = 'node_exporter'
+base_path = ['service', 'monitoring', 'node-exporter']
+service_file = '/etc/systemd/system/node_exporter.service'
+listen_if = 'dum3421'
+listen_ip = '192.0.2.1'
+
+
+class TestMonitoringNodeExporter(VyOSUnitTestSHIM.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ # call base-classes classmethod
+ super(TestMonitoringNodeExporter, cls).setUpClass()
+ # create a test interfaces
+ cls.cli_set(
+ cls, ['interfaces', 'dummy', listen_if, 'address', listen_ip + '/32']
+ )
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.cli_delete(cls, ['interfaces', 'dummy', listen_if])
+ super(TestMonitoringNodeExporter, cls).tearDownClass()
+
+ def tearDown(self):
+ self.cli_delete(base_path)
+ self.cli_commit()
+ self.assertFalse(process_named_running(PROCESS_NAME))
+
+ def test_01_basic_config(self):
+ self.cli_set(base_path + ['listen-address', listen_ip])
+
+ # commit changes
+ self.cli_commit()
+
+ file_content = read_file(service_file)
+ self.assertIn(f'{listen_ip}:9100', file_content)
+
+ # Check for running process
+ self.assertTrue(process_named_running(PROCESS_NAME))
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_vpn_ipsec.py b/smoketest/scripts/cli/test_vpn_ipsec.py
index 3b8687b93..de18d0427 100755
--- a/smoketest/scripts/cli/test_vpn_ipsec.py
+++ b/smoketest/scripts/cli/test_vpn_ipsec.py
@@ -947,7 +947,8 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
self.cli_set(base_path + ['ike-group', ike_group, 'lifetime', ike_lifetime])
self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'dh-group', '14'])
self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'encryption', 'aes256'])
- self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'hash', 'sha512'])
+ # a hash algorithm that cannot be mapped to an equivalent PRF
+ self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'hash', 'aes192gmac'])
# ESP
self.cli_set(base_path + ['esp-group', esp_group, 'lifetime', eap_lifetime])
@@ -968,6 +969,11 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
self.cli_set(base_path + ['remote-access', 'pool', ip_pool_name, 'name-server', name_server])
self.cli_set(base_path + ['remote-access', 'pool', ip_pool_name, 'prefix', prefix])
+ # verify() - IKE group use not mapped hash algorithm
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'hash', 'sha512'])
self.cli_commit()
self.assertTrue(os.path.exists(dhcp_interfaces_file))
diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py
index 5638a9668..ffbd915a2 100755
--- a/src/conf_mode/firewall.py
+++ b/src/conf_mode/firewall.py
@@ -36,11 +36,15 @@ from vyos.utils.process import cmd
from vyos.utils.process import rc_cmd
from vyos import ConfigError
from vyos import airbag
+from pathlib import Path
from subprocess import run as subp_run
airbag.enable()
nftables_conf = '/run/nftables.conf'
+domain_resolver_usage = '/run/use-vyos-domain-resolver-firewall'
+domain_resolver_usage_nat = '/run/use-vyos-domain-resolver-nat'
+
sysctl_file = r'/run/sysctl/10-vyos-firewall.conf'
valid_groups = [
@@ -128,7 +132,7 @@ def get_config(config=None):
firewall['geoip_updated'] = geoip_updated(conf, firewall)
- fqdn_config_parse(firewall)
+ fqdn_config_parse(firewall, 'firewall')
set_dependents('conntrack', conf)
@@ -570,12 +574,15 @@ def apply(firewall):
call_dependents()
- # T970 Enable a resolver (systemd daemon) that checks
- # domain-group/fqdn addresses and update entries for domains by timeout
- # If router loaded without internet connection or for synchronization
- domain_action = 'stop'
- if dict_search_args(firewall, 'group', 'domain_group') or firewall['ip_fqdn'] or firewall['ip6_fqdn']:
- domain_action = 'restart'
+ ## DOMAIN RESOLVER
+ domain_action = 'restart'
+ if dict_search_args(firewall, 'group', 'domain_group') or firewall['ip_fqdn'].items() or firewall['ip6_fqdn'].items():
+ text = f'# Automatically generated by firewall.py\nThis file indicates that vyos-domain-resolver service is used by the firewall.\n'
+ Path(domain_resolver_usage).write_text(text)
+ else:
+ Path(domain_resolver_usage).unlink(missing_ok=True)
+ if not Path('/run').glob('use-vyos-domain-resolver*'):
+ domain_action = 'stop'
call(f'systemctl {domain_action} vyos-domain-resolver.service')
if firewall['geoip_updated']:
diff --git a/src/conf_mode/nat.py b/src/conf_mode/nat.py
index 39803fa02..98b2f3f29 100755
--- a/src/conf_mode/nat.py
+++ b/src/conf_mode/nat.py
@@ -26,10 +26,13 @@ from vyos.template import is_ip_network
from vyos.utils.kernel import check_kmod
from vyos.utils.dict import dict_search
from vyos.utils.dict import dict_search_args
+from vyos.utils.file import write_file
from vyos.utils.process import cmd
from vyos.utils.process import run
+from vyos.utils.process import call
from vyos.utils.network import is_addr_assigned
from vyos.utils.network import interface_exists
+from vyos.firewall import fqdn_config_parse
from vyos import ConfigError
from vyos import airbag
@@ -39,6 +42,8 @@ k_mod = ['nft_nat', 'nft_chain_nat']
nftables_nat_config = '/run/nftables_nat.conf'
nftables_static_nat_conf = '/run/nftables_static-nat-rules.nft'
+domain_resolver_usage = '/run/use-vyos-domain-resolver-nat'
+domain_resolver_usage_firewall = '/run/use-vyos-domain-resolver-firewall'
valid_groups = [
'address_group',
@@ -71,6 +76,8 @@ def get_config(config=None):
if 'dynamic_group' in nat['firewall_group']:
del nat['firewall_group']['dynamic_group']
+ fqdn_config_parse(nat, 'nat')
+
return nat
def verify_rule(config, err_msg, groups_dict):
@@ -251,6 +258,19 @@ def apply(nat):
call_dependents()
+ # DOMAIN RESOLVER
+ if nat and 'deleted' not in nat:
+ domain_action = 'restart'
+ if nat['ip_fqdn'].items():
+ text = f'# Automatically generated by nat.py\nThis file indicates that vyos-domain-resolver service is used by nat.\n'
+ write_file(domain_resolver_usage, text)
+ elif os.path.exists(domain_resolver_usage):
+ os.unlink(domain_resolver_usage)
+ if not os.path.exists(domain_resolver_usage_firewall):
+ # Firewall not using domain resolver
+ domain_action = 'stop'
+ call(f'systemctl {domain_action} vyos-domain-resolver.service')
+
return None
if __name__ == '__main__':
diff --git a/src/conf_mode/service_monitoring_node-exporter.py b/src/conf_mode/service_monitoring_node-exporter.py
new file mode 100755
index 000000000..db34bb5d0
--- /dev/null
+++ b/src/conf_mode/service_monitoring_node-exporter.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+
+from sys import exit
+
+from vyos.config import Config
+from vyos.configdict import is_node_changed
+from vyos.configverify import verify_vrf
+from vyos.template import render
+from vyos.utils.process import call
+from vyos import ConfigError
+from vyos import airbag
+
+
+airbag.enable()
+
+service_file = '/etc/systemd/system/node_exporter.service'
+systemd_service = 'node_exporter.service'
+
+
+def get_config(config=None):
+ if config:
+ conf = config
+ else:
+ conf = Config()
+ base = ['service', 'monitoring', 'node-exporter']
+ if not conf.exists(base):
+ return None
+
+ config_data = conf.get_config_dict(
+ base, key_mangling=('-', '_'), get_first_key=True
+ )
+ config_data = conf.merge_defaults(config_data, recursive=True)
+
+ tmp = is_node_changed(conf, base + ['vrf'])
+ if tmp:
+ config_data.update({'restart_required': {}})
+
+ return config_data
+
+
+def verify(config_data):
+ # bail out early - looks like removal from running config
+ if not config_data:
+ return None
+
+ verify_vrf(config_data)
+ return None
+
+
+def generate(config_data):
+ if not config_data:
+ # Delete systemd files
+ if os.path.isfile(service_file):
+ os.unlink(service_file)
+ return None
+
+ # Render node_exporter service_file
+ render(service_file, 'node_exporter/node_exporter.service.j2', config_data)
+ return None
+
+
+def apply(config_data):
+ # Reload systemd manager configuration
+ call('systemctl daemon-reload')
+ if not config_data:
+ call(f'systemctl stop {systemd_service}')
+ return
+
+ # we need to restart the service if e.g. the VRF name changed
+ systemd_action = 'reload-or-restart'
+ if 'restart_required' in config_data:
+ systemd_action = 'restart'
+
+ call(f'systemctl {systemd_action} {systemd_service}')
+
+
+if __name__ == '__main__':
+ try:
+ c = get_config()
+ verify(c)
+ generate(c)
+ apply(c)
+ except ConfigError as e:
+ print(e)
+ exit(1)
diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py
index ca0c3657f..e22b7550c 100755
--- a/src/conf_mode/vpn_ipsec.py
+++ b/src/conf_mode/vpn_ipsec.py
@@ -214,6 +214,19 @@ def verify(ipsec):
else:
verify_interface_exists(ipsec, interface)
+ # need to use a pseudo-random function (PRF) with an authenticated encryption algorithm.
+ # If a hash algorithm is defined then it will be mapped to an equivalent PRF
+ if 'ike_group' in ipsec:
+ for _, ike_config in ipsec['ike_group'].items():
+ for proposal, proposal_config in ike_config.get('proposal', {}).items():
+ if 'encryption' in proposal_config and 'prf' not in proposal_config:
+ # list of hash algorithms that cannot be mapped to an equivalent PRF
+ algs = ['aes128gmac', 'aes192gmac', 'aes256gmac', 'sha256_96']
+ if 'hash' in proposal_config and proposal_config['hash'] in algs:
+ raise ConfigError(
+ f"A PRF algorithm is mandatory in IKE proposal {proposal}"
+ )
+
if 'l2tp' in ipsec:
if 'esp_group' in ipsec['l2tp']:
if 'esp_group' not in ipsec or ipsec['l2tp']['esp_group'] not in ipsec['esp_group']:
diff --git a/src/helpers/vyos-domain-resolver.py b/src/helpers/vyos-domain-resolver.py
index 57cfcabd7..f5a1d9297 100755
--- a/src/helpers/vyos-domain-resolver.py
+++ b/src/helpers/vyos-domain-resolver.py
@@ -30,6 +30,8 @@ from vyos.xml_ref import get_defaults
base = ['firewall']
timeout = 300
cache = False
+base_firewall = ['firewall']
+base_nat = ['nat']
domain_state = {}
@@ -46,25 +48,25 @@ ipv6_tables = {
'ip6 raw'
}
-def get_config(conf):
- firewall = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True,
+def get_config(conf, node):
+ node_config = conf.get_config_dict(node, key_mangling=('-', '_'), get_first_key=True,
no_tag_node_value_mangle=True)
- default_values = get_defaults(base, get_first_key=True)
+ default_values = get_defaults(node, get_first_key=True)
- firewall = dict_merge(default_values, firewall)
+ node_config = dict_merge(default_values, node_config)
global timeout, cache
- if 'resolver_interval' in firewall:
- timeout = int(firewall['resolver_interval'])
+ if 'resolver_interval' in node_config:
+ timeout = int(node_config['resolver_interval'])
- if 'resolver_cache' in firewall:
+ if 'resolver_cache' in node_config:
cache = True
- fqdn_config_parse(firewall)
+ fqdn_config_parse(node_config, node[0])
- return firewall
+ return node_config
def resolve(domains, ipv6=False):
global domain_state
@@ -108,55 +110,60 @@ def nft_valid_sets():
except:
return []
-def update(firewall):
+def update_fqdn(config, node):
conf_lines = []
count = 0
-
valid_sets = nft_valid_sets()
- domain_groups = dict_search_args(firewall, 'group', 'domain_group')
- if domain_groups:
- for set_name, domain_config in domain_groups.items():
- if 'address' not in domain_config:
- continue
-
- nft_set_name = f'D_{set_name}'
- domains = domain_config['address']
-
- ip_list = resolve(domains, ipv6=False)
- for table in ipv4_tables:
- if (table, nft_set_name) in valid_sets:
- conf_lines += nft_output(table, nft_set_name, ip_list)
-
- ip6_list = resolve(domains, ipv6=True)
- for table in ipv6_tables:
- if (table, nft_set_name) in valid_sets:
- conf_lines += nft_output(table, nft_set_name, ip6_list)
+ if node == 'firewall':
+ domain_groups = dict_search_args(config, 'group', 'domain_group')
+ if domain_groups:
+ for set_name, domain_config in domain_groups.items():
+ if 'address' not in domain_config:
+ continue
+ nft_set_name = f'D_{set_name}'
+ domains = domain_config['address']
+
+ ip_list = resolve(domains, ipv6=False)
+ for table in ipv4_tables:
+ if (table, nft_set_name) in valid_sets:
+ conf_lines += nft_output(table, nft_set_name, ip_list)
+ ip6_list = resolve(domains, ipv6=True)
+ for table in ipv6_tables:
+ if (table, nft_set_name) in valid_sets:
+ conf_lines += nft_output(table, nft_set_name, ip6_list)
+ count += 1
+
+ for set_name, domain in config['ip_fqdn'].items():
+ table = 'ip vyos_filter'
+ nft_set_name = f'FQDN_{set_name}'
+ ip_list = resolve([domain], ipv6=False)
+ if (table, nft_set_name) in valid_sets:
+ conf_lines += nft_output(table, nft_set_name, ip_list)
count += 1
- for set_name, domain in firewall['ip_fqdn'].items():
- table = 'ip vyos_filter'
- nft_set_name = f'FQDN_{set_name}'
-
- ip_list = resolve([domain], ipv6=False)
-
- if (table, nft_set_name) in valid_sets:
- conf_lines += nft_output(table, nft_set_name, ip_list)
- count += 1
-
- for set_name, domain in firewall['ip6_fqdn'].items():
- table = 'ip6 vyos_filter'
- nft_set_name = f'FQDN_{set_name}'
+ for set_name, domain in config['ip6_fqdn'].items():
+ table = 'ip6 vyos_filter'
+ nft_set_name = f'FQDN_{set_name}'
+ ip_list = resolve([domain], ipv6=True)
+ if (table, nft_set_name) in valid_sets:
+ conf_lines += nft_output(table, nft_set_name, ip_list)
+ count += 1
- ip_list = resolve([domain], ipv6=True)
- if (table, nft_set_name) in valid_sets:
- conf_lines += nft_output(table, nft_set_name, ip_list)
- count += 1
+ else:
+ # It's NAT
+ for set_name, domain in config['ip_fqdn'].items():
+ table = 'ip vyos_nat'
+ nft_set_name = f'FQDN_nat_{set_name}'
+ ip_list = resolve([domain], ipv6=False)
+ if (table, nft_set_name) in valid_sets:
+ conf_lines += nft_output(table, nft_set_name, ip_list)
+ count += 1
nft_conf_str = "\n".join(conf_lines) + "\n"
code = run(f'nft --file -', input=nft_conf_str)
- print(f'Updated {count} sets - result: {code}')
+ print(f'Updated {count} sets in {node} - result: {code}')
if __name__ == '__main__':
print(f'VyOS domain resolver')
@@ -169,10 +176,12 @@ if __name__ == '__main__':
time.sleep(1)
conf = ConfigTreeQuery()
- firewall = get_config(conf)
+ firewall = get_config(conf, base_firewall)
+ nat = get_config(conf, base_nat)
print(f'interval: {timeout}s - cache: {cache}')
while True:
- update(firewall)
+ update_fqdn(firewall, 'firewall')
+ update_fqdn(nat, 'nat')
time.sleep(timeout)
diff --git a/src/systemd/vyos-domain-resolver.service b/src/systemd/vyos-domain-resolver.service
index c56b51f0c..e63ae5e34 100644
--- a/src/systemd/vyos-domain-resolver.service
+++ b/src/systemd/vyos-domain-resolver.service
@@ -1,6 +1,7 @@
[Unit]
Description=VyOS firewall domain resolver
After=vyos-router.service
+ConditionPathExistsGlob=/run/use-vyos-domain-resolver*
[Service]
Type=simple
diff --git a/src/utils/vyos-show-config b/src/utils/vyos-show-config
new file mode 100755
index 000000000..152322fc1
--- /dev/null
+++ b/src/utils/vyos-show-config
@@ -0,0 +1,57 @@
+#!/usr/bin/env python3
+# Copyright (C) 2024 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import sys
+import argparse
+
+from signal import signal, SIGPIPE, SIG_DFL
+
+def get_config(path):
+ from vyos.utils.process import rc_cmd
+ res, out = rc_cmd(f"cli-shell-api showCfg {path}")
+ if res > 0:
+ print("Error: failed to retrieve the config", file=sys.stderr)
+ sys.exit(1)
+ else:
+ return out
+
+def strip_config(config):
+ from vyos.utils.strip_config import strip_config_source
+ return strip_config_source(config)
+
+if __name__ == '__main__':
+ signal(SIGPIPE,SIG_DFL)
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--strip-private",
+ help="Strip private information from the config",
+ action="store_true")
+
+ args, path_args = parser.parse_known_args()
+
+ config = get_config(" ".join(path_args))
+
+ if args.strip_private:
+ edit_level = os.getenv("VYATTA_EDIT_LEVEL")
+ if (edit_level != "/") or (len(path_args) > 0):
+ print("Error: show --strip-private only works at the top level",
+ file=sys.stderr)
+ sys.exit(1)
+ else:
+ print(strip_config(config))
+ else:
+ print(config)
diff --git a/src/validators/ipv4-range b/src/validators/ipv4-range
index 6492bfc52..7bf271bbb 100755
--- a/src/validators/ipv4-range
+++ b/src/validators/ipv4-range
@@ -1,40 +1,10 @@
-#!/bin/bash
+#!/bin/sh
-# snippet from https://stackoverflow.com/questions/10768160/ip-address-converter
-ip2dec () {
- local a b c d ip=$@
- IFS=. read -r a b c d <<< "$ip"
- printf '%d\n' "$((a * 256 ** 3 + b * 256 ** 2 + c * 256 + d))"
-}
+ipaddrcheck --verbose --is-ipv4-range "$1"
-error_exit() {
- echo "Error: $1 is not a valid IPv4 address range"
- exit 1
-}
-
-# Only run this if there is a hypen present in $1
-if [[ "$1" =~ "-" ]]; then
- # This only works with real bash (<<<) - split IP addresses into array with
- # hyphen as delimiter
- readarray -d - -t strarr <<< $1
-
- ipaddrcheck --is-ipv4-single ${strarr[0]}
- if [ $? -gt 0 ]; then
- error_exit $1
- fi
-
- ipaddrcheck --is-ipv4-single ${strarr[1]}
- if [ $? -gt 0 ]; then
- error_exit $1
- fi
-
- start=$(ip2dec ${strarr[0]})
- stop=$(ip2dec ${strarr[1]})
- if [ $start -ge $stop ]; then
- error_exit $1
- fi
-
- exit 0
+if [ $? -gt 0 ]; then
+ echo "Error: $1 is not a valid IPv4 address range"
+ exit 1
fi
-error_exit $1
+exit 0
diff --git a/src/validators/ipv6-range b/src/validators/ipv6-range
index 7080860c4..0d2eb6384 100755
--- a/src/validators/ipv6-range
+++ b/src/validators/ipv6-range
@@ -1,20 +1,10 @@
-#!/usr/bin/env python3
+#!/bin/sh
-from ipaddress import IPv6Address
-from sys import argv, exit
+ipaddrcheck --verbose --is-ipv6-range "$1"
-if __name__ == '__main__':
- if len(argv) > 1:
- # try to pass validation and raise an error if failed
- try:
- ipv6_range = argv[1]
- range_left = ipv6_range.split('-')[0]
- range_right = ipv6_range.split('-')[1]
- if not IPv6Address(range_left) < IPv6Address(range_right):
- raise ValueError(f'left element {range_left} must be less than right element {range_right}')
- except Exception as err:
- print(f'Error: {ipv6_range} is not a valid IPv6 range: {err}')
- exit(1)
- else:
- print('Error: an IPv6 range argument must be provided')
- exit(1)
+if [ $? -gt 0 ]; then
+ echo "Error: $1 is not a valid IPv6 address range"
+ exit 1
+fi
+
+exit 0