summaryrefslogtreecommitdiff
path: root/data
diff options
context:
space:
mode:
Diffstat (limited to 'data')
-rw-r--r--data/config-mode-dependencies/vyos-1x.json51
-rw-r--r--data/config-mode-dependencies/vyos-vpp.json54
-rw-r--r--data/config-sync-exclude.json17
-rw-r--r--data/config.boot.default15
-rw-r--r--data/op-mode-standardized.json7
-rw-r--r--data/templates/accel-ppp/chap-secrets.config_dict.j22
-rw-r--r--data/templates/accel-ppp/chap-secrets.ipoe.j22
-rw-r--r--data/templates/accel-ppp/ipoe.config.j211
-rw-r--r--data/templates/accel-ppp/pppoe.config.j27
-rw-r--r--data/templates/aws/override_aws_gwlbtun.conf.j24
-rw-r--r--data/templates/chrony/chrony.conf.j222
-rw-r--r--data/templates/conntrack/nftables-ct.j236
-rw-r--r--data/templates/conntrack/sysctl.conf.j23
-rw-r--r--data/templates/conntrack/vyos_nf_conntrack.conf.j22
-rw-r--r--data/templates/conntrackd/conntrackd.conf.j21
-rw-r--r--data/templates/conserver/dropbear@.service.j22
-rw-r--r--data/templates/container/containers.conf.j24
-rw-r--r--data/templates/container/registries.conf.j210
-rw-r--r--data/templates/dhcp-client/ipv6.j26
-rw-r--r--data/templates/dhcp-client/ipv6.override.conf.j23
-rw-r--r--data/templates/dhcp-server/10-override.conf.j22
-rw-r--r--data/templates/dhcp-server/kea-ctrl-agent.conf.j214
-rw-r--r--data/templates/dhcp-server/kea-dhcp-ddns.conf.j235
-rw-r--r--data/templates/dhcp-server/kea-dhcp4.conf.j273
-rw-r--r--data/templates/dhcp-server/kea-dhcp6.conf.j225
-rw-r--r--data/templates/dns-dynamic/ddclient.conf.j24
-rw-r--r--data/templates/dns-dynamic/override.conf.j26
-rw-r--r--data/templates/firewall/nftables-bridge.j22
-rw-r--r--data/templates/firewall/nftables-defines.j220
-rw-r--r--data/templates/firewall/nftables-geoip-update.j245
-rw-r--r--data/templates/firewall/nftables-nat.j213
-rw-r--r--data/templates/firewall/nftables-policy.j217
-rw-r--r--data/templates/firewall/nftables-zone.j276
-rwxr-xr-xdata/templates/firewall/nftables.j2101
-rw-r--r--data/templates/firewall/sysctl-firewall.conf.j22
-rw-r--r--data/templates/frr/babeld.frr.j22
-rw-r--r--data/templates/frr/bgpd.frr.j254
-rw-r--r--data/templates/frr/daemons.frr.tmpl11
-rw-r--r--data/templates/frr/distribute_list_macro.j23
-rw-r--r--data/templates/frr/evpn.mh.frr.j228
-rw-r--r--data/templates/frr/fabricd.frr.j23
-rw-r--r--data/templates/frr/ipv6_distribute_list_macro.j23
-rw-r--r--data/templates/frr/isisd.frr.j268
-rw-r--r--data/templates/frr/ldpd.frr.j210
-rw-r--r--data/templates/frr/nhrpd.frr.j260
-rw-r--r--data/templates/frr/nhrpd_nftables.conf.j246
-rw-r--r--data/templates/frr/ospfd.frr.j217
-rw-r--r--data/templates/frr/pim6d.frr.j221
-rw-r--r--data/templates/frr/pimd.frr.j236
-rw-r--r--data/templates/frr/policy.frr.j29
-rw-r--r--data/templates/frr/rpki.frr.j232
-rw-r--r--data/templates/frr/static_mcast.frr.j211
-rw-r--r--data/templates/frr/static_routes_macro.j229
-rw-r--r--data/templates/frr/staticd.frr.j299
-rw-r--r--data/templates/frr/zebra.route-map.frr.j28
-rw-r--r--data/templates/frr/zebra.segment_routing.frr.j263
-rw-r--r--data/templates/frr/zebra.traffic_engineering.frr.j237
-rw-r--r--data/templates/frr/zebra.vrf.route-map.frr.j22
-rw-r--r--data/templates/getty/serial-getty.service.j22
-rw-r--r--data/templates/grub/grub_common.j22
-rw-r--r--data/templates/grub/grub_compat.j24
-rw-r--r--data/templates/grub/grub_options.j27
-rw-r--r--data/templates/grub/grub_vyos_version.j22
-rw-r--r--data/templates/high-availability/keepalived.conf.j211
-rw-r--r--data/templates/https/nginx.default.j23
-rw-r--r--data/templates/ids/fastnetmon.j2121
-rw-r--r--data/templates/ids/fastnetmon_excluded_networks_list.j25
-rw-r--r--data/templates/ids/fastnetmon_networks_list.j25
-rw-r--r--data/templates/igmp-proxy/igmpproxy.conf.j22
-rw-r--r--data/templates/ipsec/charon.j221
-rw-r--r--data/templates/ipsec/charon_logging.conf.j218
-rw-r--r--data/templates/ipsec/charon_systemd.conf.j218
-rw-r--r--data/templates/ipsec/ios_profile.j26
-rw-r--r--data/templates/ipsec/swanctl.conf.j235
-rw-r--r--data/templates/ipsec/swanctl/l2tp.j25
-rw-r--r--data/templates/ipsec/swanctl/peer.j251
-rw-r--r--data/templates/ipsec/swanctl/profile.j213
-rw-r--r--data/templates/ipsec/swanctl/remote_access.j214
-rw-r--r--data/templates/ipt-netflow/ipt_NETFLOW.conf.j229
-rw-r--r--data/templates/lcd/LCDd.conf.j27
-rw-r--r--data/templates/lldp/vyos.conf.j211
-rw-r--r--data/templates/load-balancing/haproxy.cfg.j284
-rw-r--r--data/templates/load-balancing/nftables-wlb.j268
-rw-r--r--data/templates/load-balancing/wlb.conf.j2134
-rw-r--r--data/templates/login/authorized_keys.j21
-rw-r--r--data/templates/login/authorized_principals.j24
-rw-r--r--data/templates/login/motd_user_dsa_warning.j218
-rw-r--r--data/templates/login/motd_vyos_nonproduction.j25
-rw-r--r--data/templates/login/pam_radius_auth.conf.j24
-rw-r--r--data/templates/login/tacplus_nss.conf.j25
-rw-r--r--data/templates/login/tacplus_servers.j22
-rw-r--r--data/templates/logs/logrotate/vyos-rsyslog.j22
-rw-r--r--data/templates/mdns-repeater/avahi-daemon.conf.j23
-rw-r--r--data/templates/ndppd/ndppd.conf.j22
-rw-r--r--data/templates/nhrp/nftables.conf.j217
-rw-r--r--data/templates/nhrp/opennhrp.conf.j242
-rw-r--r--data/templates/ocserv/ocserv_config.j217
-rw-r--r--data/templates/ocserv/radius_conf.j22
-rw-r--r--data/templates/openvpn/server.conf.j23
-rw-r--r--data/templates/pmacct/override.conf.j217
-rw-r--r--data/templates/pmacct/uacctd.conf.j280
-rw-r--r--data/templates/pppoe/peer.j22
-rw-r--r--data/templates/prometheus/blackbox_exporter.service.j221
-rw-r--r--data/templates/prometheus/blackbox_exporter.yml.j223
-rw-r--r--data/templates/prometheus/frr_exporter.service.j221
-rw-r--r--data/templates/prometheus/node_exporter.service.j226
-rw-r--r--data/templates/protocols/systemd_vyos_failover_service.j22
-rw-r--r--data/templates/router-advert/radvd.conf.j221
-rw-r--r--data/templates/rsyslog/logrotate.j221
-rw-r--r--data/templates/rsyslog/override.conf.j211
-rw-r--r--data/templates/rsyslog/rsyslog.conf.j2206
-rw-r--r--data/templates/sflow/hsflowd.conf.j28
-rw-r--r--data/templates/snmp/etc.snmpd.conf.j210
-rw-r--r--data/templates/snmp/override.conf.j22
-rw-r--r--data/templates/snmp/var.snmpd.conf.j22
-rw-r--r--data/templates/squid/squid.conf.j28
-rw-r--r--data/templates/ssh/motd_ssh_dsa_warning.j28
-rw-r--r--data/templates/ssh/sshd_config.j236
-rw-r--r--data/templates/system/watchdog.conf.j25
-rw-r--r--data/templates/telegraf/syslog_telegraf.j24
-rw-r--r--data/templates/telegraf/telegraf.j211
-rw-r--r--data/templates/vpp/override.conf.j218
-rw-r--r--data/templates/vpp/startup.conf.j2193
-rw-r--r--data/templates/wifi/hostapd.conf.j24
-rw-r--r--data/templates/zabbix-agent/zabbix-agent.conf.j213
-rw-r--r--data/vyos-firewall-init.conf4
126 files changed, 2078 insertions, 850 deletions
diff --git a/data/config-mode-dependencies/vyos-1x.json b/data/config-mode-dependencies/vyos-1x.json
index 2981a0851..6b9cc0e42 100644
--- a/data/config-mode-dependencies/vyos-1x.json
+++ b/data/config-mode-dependencies/vyos-1x.json
@@ -5,14 +5,46 @@
},
"firewall": {
"conntrack": ["system_conntrack"],
- "group_resync": ["system_conntrack", "nat", "policy_route"]
+ "group_resync": ["system_conntrack", "nat", "nat66", "policy_route", "load-balancing_wan"]
},
"interfaces_bonding": {
- "ethernet": ["interfaces_ethernet"]
+ "ethernet": ["interfaces_ethernet"],
+ "static_arp": ["protocols_static_arp"]
},
"interfaces_bridge": {
"vxlan": ["interfaces_vxlan"],
- "wlan": ["interfaces_wireless"]
+ "wlan": ["interfaces_wireless"],
+ "static_arp": ["protocols_static_arp"]
+ },
+ "interfaces_ethernet": {
+ "static_arp": ["protocols_static_arp"]
+ },
+ "interfaces_geneve": {
+ "static_arp": ["protocols_static_arp"]
+ },
+ "interfaces_l2tpv3": {
+ "static_arp": ["protocols_static_arp"]
+ },
+ "interfaces_macsec": {
+ "static_arp": ["protocols_static_arp"]
+ },
+ "interfaces_pseudo_ethernet": {
+ "static_arp": ["protocols_static_arp"]
+ },
+ "interfaces_virtual_ethernet": {
+ "static_arp": ["protocols_static_arp"]
+ },
+ "interfaces_vxlan": {
+ "static_arp": ["protocols_static_arp"]
+ },
+ "interfaces_wireless": {
+ "static_arp": ["protocols_static_arp"]
+ },
+ "interfaces_wwan": {
+ "static_arp": ["protocols_static_arp"]
+ },
+ "interfaces_wireguard": {
+ "vxlan": ["interfaces_vxlan"]
},
"load_balancing_wan": {
"conntrack": ["system_conntrack"]
@@ -26,11 +58,12 @@
"pki": {
"ethernet": ["interfaces_ethernet"],
"openvpn": ["interfaces_openvpn"],
+ "haproxy": ["load-balancing_haproxy"],
"https": ["service_https"],
"ipsec": ["vpn_ipsec"],
"openconnect": ["vpn_openconnect"],
- "reverse_proxy": ["load-balancing_reverse-proxy"],
"rpki": ["protocols_rpki"],
+ "ssh": ["service_ssh"],
"sstp": ["vpn_sstp"],
"sstpc": ["interfaces_sstpc"],
"stunnel": ["service_stunnel"]
@@ -70,8 +103,18 @@
"system_ipv6": {
"sysctl": ["system_sysctl"]
},
+ "system_login": {
+ "ssh": ["service_ssh"]
+ },
"system_option": {
"ip_ipv6": ["system_ip", "system_ipv6"],
+ "firewall": ["firewall"],
"sysctl": ["system_sysctl"]
+ },
+ "system_logs": {
+ "syslog": ["system_syslog"]
+ },
+ "system_sflow": {
+ "vpp_sflow": ["vpp_sflow"]
}
}
diff --git a/data/config-mode-dependencies/vyos-vpp.json b/data/config-mode-dependencies/vyos-vpp.json
new file mode 100644
index 000000000..af7a8ca0d
--- /dev/null
+++ b/data/config-mode-dependencies/vyos-vpp.json
@@ -0,0 +1,54 @@
+{
+ "vpp": {
+ "ethernet": ["interfaces_ethernet"],
+ "vpp_interfaces_bonding": ["vpp_interfaces_bonding"],
+ "vpp_interfaces_bridge": ["vpp_interfaces_bridge"],
+ "vpp_interfaces_gre": ["vpp_interfaces_gre"],
+ "vpp_interfaces_ipip": ["vpp_interfaces_ipip"],
+ "vpp_interfaces_loopback": ["vpp_interfaces_loopback"],
+ "vpp_interfaces_vxlan": ["vpp_interfaces_vxlan"],
+ "vpp_interfaces_xconnect": ["vpp_interfaces_xconnect"],
+ "vpp_acl": ["vpp_acl"],
+ "vpp_ipfix": ["vpp_ipfix"],
+ "vpp_nat_nat44": ["vpp_nat_nat44"],
+ "vpp_nat_cgnat": ["vpp_nat_cgnat"],
+ "vpp_sflow": ["vpp_sflow"],
+ "pppoe_server": ["service_pppoe-server"]
+ },
+ "vpp_interfaces_bonding": {
+ "vpp_interfaces_xconnect": ["vpp_interfaces_xconnect"],
+ "vpp_interfaces_bridge": ["vpp_interfaces_bridge"],
+ "vpp_acl": ["vpp_acl"],
+ "vpp_nat_nat44": ["vpp_nat_nat44"],
+ "vpp_nat_cgnat": ["vpp_nat_cgnat"],
+ "vpp_ipfix": ["vpp_ipfix"],
+ "pppoe_server": ["service_pppoe-server"]
+ },
+ "vpp_interfaces_gre": {
+ "vpp_interfaces_xconnect": ["vpp_interfaces_xconnect"],
+ "vpp_interfaces_bridge": ["vpp_interfaces_bridge"],
+ "vpp_acl": ["vpp_acl"],
+ "vpp_nat_nat44": ["vpp_nat_nat44"],
+ "vpp_nat_cgnat": ["vpp_nat_cgnat"]
+ },
+ "vpp_interfaces_ipip": {
+ "vpp_interfaces_xconnect": ["vpp_interfaces_xconnect"],
+ "vpp_acl": ["vpp_acl"],
+ "vpp_nat_nat44": ["vpp_nat_nat44"],
+ "vpp_nat_cgnat": ["vpp_nat_cgnat"]
+ },
+ "vpp_interfaces_loopback": {
+ "vpp_interfaces_bridge": ["vpp_interfaces_bridge"],
+ "vpp_acl": ["vpp_acl"],
+ "vpp_nat_nat44": ["vpp_nat_nat44"],
+ "vpp_nat_cgnat": ["vpp_nat_cgnat"]
+ },
+ "vpp_interfaces_vxlan": {
+ "vpp_interfaces_bridge": ["vpp_interfaces_bridge"],
+ "vpp_interfaces_xconnect": ["vpp_interfaces_xconnect"],
+ "vpp_acl": ["vpp_acl"],
+ "vpp_nat_nat44": ["vpp_nat_nat44"],
+ "vpp_nat_cgnat": ["vpp_nat_cgnat"]
+ }
+}
+
diff --git a/data/config-sync-exclude.json b/data/config-sync-exclude.json
new file mode 100644
index 000000000..dc4cb88e8
--- /dev/null
+++ b/data/config-sync-exclude.json
@@ -0,0 +1,17 @@
+[
+ [
+ "interfaces",
+ "ethernet",
+ "hw-id"
+ ],
+ [
+ "interfaces",
+ "ethernet",
+ "address"
+ ],
+ [
+ "interfaces",
+ "ethernet",
+ "offload"
+ ]
+]
diff --git a/data/config.boot.default b/data/config.boot.default
index 93369d9b7..4145515f1 100644
--- a/data/config.boot.default
+++ b/data/config.boot.default
@@ -26,13 +26,13 @@ system {
config-management {
commit-revisions "100"
}
- console {
- device ttyS0 {
- speed "115200"
- }
- }
host-name "vyos"
login {
+ operator-group default {
+ command-policy {
+ allow "*"
+ }
+ }
user vyos {
authentication {
encrypted-password "$6$QxPS.uk6mfo$9QBSo8u1FkH16gMyAVhus6fU3LOzvLR9Z9.82m3tiHFAxTtIkhaZSWssSgzt4v4dGAL8rhVQxTg0oAG9/q11h/"
@@ -40,8 +40,11 @@ system {
}
}
}
+ option {
+ reboot-on-upgrade-failure 5
+ }
syslog {
- global {
+ local {
facility all {
level "info"
}
diff --git a/data/op-mode-standardized.json b/data/op-mode-standardized.json
index baa1e9110..3dff070a1 100644
--- a/data/op-mode-standardized.json
+++ b/data/op-mode-standardized.json
@@ -5,6 +5,7 @@
"bridge.py",
"cgnat.py",
"config_mgmt.py",
+"config_sync.py",
"conntrack.py",
"container.py",
"cpu.py",
@@ -13,23 +14,25 @@
"evpn.py",
"interfaces.py",
"ipsec.py",
+"load-balancing_wan.py",
"lldp.py",
"log.py",
"memory.py",
"multicast.py",
"nat.py",
"neighbor.py",
-"nhrp.py",
"openconnect.py",
"openvpn.py",
"otp.py",
"qos.py",
"reset_vpn.py",
-"reverseproxy.py",
+"load-balancing_haproxy.py",
"route.py",
"storage.py",
+"stp.py",
"system.py",
"uptime.py",
"version.py",
+"vpp.py",
"vrf.py"
]
diff --git a/data/templates/accel-ppp/chap-secrets.config_dict.j2 b/data/templates/accel-ppp/chap-secrets.config_dict.j2
index 51e66d57c..393413cc6 100644
--- a/data/templates/accel-ppp/chap-secrets.config_dict.j2
+++ b/data/templates/accel-ppp/chap-secrets.config_dict.j2
@@ -1,6 +1,6 @@
# username server password acceptable local IP addresses shaper
{% if authentication.local_users.username is vyos_defined %}
-{% for user, user_config in authentication.local_users.username.items() if user_config.disabled is not vyos_defined %}
+{% for user, user_config in authentication.local_users.username.items() if user_config.disable is not vyos_defined %}
{% if user_config.rate_limit is vyos_defined %}
{{ "%-12s" | format(user) }} * {{ "%-16s" | format(user_config.password) }} {{ "%-16s" | format(user_config.static_ip) }} {{ user_config.rate_limit.download }}/{{ user_config.rate_limit.upload }}
{% else %}
diff --git a/data/templates/accel-ppp/chap-secrets.ipoe.j2 b/data/templates/accel-ppp/chap-secrets.ipoe.j2
index 43083e22e..59b9dfc8d 100644
--- a/data/templates/accel-ppp/chap-secrets.ipoe.j2
+++ b/data/templates/accel-ppp/chap-secrets.ipoe.j2
@@ -6,7 +6,7 @@
{% if mac_config.vlan is vyos_defined %}
{% set iface = iface ~ '.' ~ mac_config.vlan %}
{% endif %}
-{{ "%-11s" | format(iface) }} * {{ mac | lower }} * {{ mac_config.rate_limit.download ~ '/' ~ mac_config.rate_limit.upload if mac_config.rate_limit.download is vyos_defined and mac_config.rate_limit.upload is vyos_defined }}
+{{ "%-11s" | format(iface) }} * {{ mac | lower }} {{ mac_config.ip_address if mac_config.ip_address is vyos_defined else '*' }} {{ mac_config.rate_limit.download ~ '/' ~ mac_config.rate_limit.upload if mac_config.rate_limit.download is vyos_defined and mac_config.rate_limit.upload is vyos_defined }}
{% endfor %}
{% endif %}
{% endfor %}
diff --git a/data/templates/accel-ppp/ipoe.config.j2 b/data/templates/accel-ppp/ipoe.config.j2
index 81f63c53b..b0f83a0d6 100644
--- a/data/templates/accel-ppp/ipoe.config.j2
+++ b/data/templates/accel-ppp/ipoe.config.j2
@@ -38,6 +38,12 @@ level={{ log.level }}
[ipoe]
verbose=1
+{% if idle_timeout is vyos_defined %}
+idle-timeout={{ idle_timeout }}
+{% endif %}
+{% if lua_file is vyos_defined %}
+lua-file={{ lua_file }}
+{% endif %}
{% if interface is vyos_defined %}
{% for iface, iface_config in interface.items() %}
{% set tmp = 'interface=' %}
@@ -55,7 +61,10 @@ verbose=1
{% set range = 'range=' ~ iface_config.client_subnet ~ ',' if iface_config.client_subnet is vyos_defined else '' %}
{% set relay = ',' ~ 'relay=' ~ iface_config.external_dhcp.dhcp_relay if iface_config.external_dhcp.dhcp_relay is vyos_defined else '' %}
{% set giaddr = ',' ~ 'giaddr=' ~ iface_config.external_dhcp.giaddr if iface_config.external_dhcp.giaddr is vyos_defined else '' %}
-{{ tmp }},{{ shared }}mode={{ iface_config.mode | upper }},ifcfg=1,{{ range }}start=dhcpv4,ipv6=1{{ relay }}{{ giaddr }}
+{% set username = ',' ~ 'username=lua:' ~ iface_config.lua_username if iface_config.lua_username is vyos_defined else '' %}
+{% set start_map = {'dhcp': 'dhcpv4', 'unclassified-packet': 'up', 'auto': 'auto'} %}
+{% set start = start_map[iface_config.start_session] %}
+{{ tmp }},{{ shared }}mode={{ iface_config.mode | upper }},ifcfg=1,{{ range }}start={{ start }},ipv6=1{{ relay }}{{ giaddr }}{{ username }}
{% if iface_config.vlan_mon is vyos_defined %}
vlan-mon={{ iface }},{{ iface_config.vlan | join(',') }}
{% endif %}
diff --git a/data/templates/accel-ppp/pppoe.config.j2 b/data/templates/accel-ppp/pppoe.config.j2
index cf952c687..f0a4ff694 100644
--- a/data/templates/accel-ppp/pppoe.config.j2
+++ b/data/templates/accel-ppp/pppoe.config.j2
@@ -20,6 +20,7 @@ connlimit
sigchld
pppd_compat
{% endif %}
+vyos_vpp
[core]
thread-count={{ thread_count }}
@@ -55,12 +56,16 @@ verbose=1
ac-name={{ access_concentrator }}
{% if interface is vyos_defined %}
{% for iface, iface_config in interface.items() %}
+{% set vpp_cp_opt = ',vpp-cp=true' if iface_config.vpp_cp is vyos_defined else '' %}
{% if iface_config.vlan is not vyos_defined %}
-interface={{ iface }}
+interface={{ iface }}{{ vpp_cp_opt }}
{% else %}
{% for vlan in iface_config.vlan %}
interface=re:^{{ iface }}\.{{ vlan | range_to_regex }}$
{% endfor %}
+{% if iface_config.combined is vyos_defined %}
+interface={{ iface }}{{ vpp_cp_opt }}
+{% endif %}
{% if iface_config.vlan_mon is vyos_defined %}
vlan-mon={{ iface }},{{ iface_config.vlan | join(',') }}
{% endif %}
diff --git a/data/templates/aws/override_aws_gwlbtun.conf.j2 b/data/templates/aws/override_aws_gwlbtun.conf.j2
index 4c566d852..e7e60dc95 100644
--- a/data/templates/aws/override_aws_gwlbtun.conf.j2
+++ b/data/templates/aws/override_aws_gwlbtun.conf.j2
@@ -30,7 +30,7 @@ After=vyos-router.service
[Service]
EnvironmentFile=
-ExecStart=/usr/bin/gwlbtun {{ args | join(' ') }}
-CapabilityBoundingSet=CAP_NET_ADMIN
+ExecStart=/usr/sbin/gwlbtun {{ args | join(' ') }}
+CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW
Restart=always
RestartSec=10
diff --git a/data/templates/chrony/chrony.conf.j2 b/data/templates/chrony/chrony.conf.j2
index e3f078fdc..23b452f01 100644
--- a/data/templates/chrony/chrony.conf.j2
+++ b/data/templates/chrony/chrony.conf.j2
@@ -42,10 +42,15 @@ user {{ user }}
{% if config.pool is vyos_defined %}
{% set association = 'pool' %}
{% endif %}
-{{ association }} {{ server | replace('_', '-') }} iburst {{ 'nts' if config.nts is vyos_defined }} {{ 'noselect' if config.noselect is vyos_defined }} {{ 'prefer' if config.prefer is vyos_defined }}
+{{ association }} {{ server | replace('_', '-') }} iburst {{- ' nts' if config.nts is vyos_defined }} {{- ' noselect' if config.noselect is vyos_defined }} {{- ' prefer' if config.prefer is vyos_defined }} {{- ' xleave' if config.interleave is vyos_defined }} {{- ' port ' ~ ptp.port if ptp.port is vyos_defined and config.ptp is vyos_defined }}
{% endfor %}
{% endif %}
+{% if local_stratum is vyos_defined %}
+# Enable local reference mode
+local stratum {{ local_stratum }}
+{% endif %}
+
# Allowed clients configuration
{% if allow_client.address is vyos_defined %}
{% for address in allow_client.address %}
@@ -66,3 +71,18 @@ bindaddress {{ address }}
binddevice {{ interface }}
{% endif %}
{% endif %}
+
+{% if timestamp.interface is vyos_defined %}
+# Enable hardware timestamping on the specified interfaces
+{% for iface, iface_config in timestamp.interface.items() %}
+{% if iface == "all" %}
+{% set iface = "*" %}
+{% endif %}
+hwtimestamp {{ iface }} {{- ' rxfilter ' ~ iface_config.receive_filter if iface_config.receive_filter is vyos_defined }}
+{% endfor %}
+{% endif %}
+
+{% if ptp.port is vyos_defined %}
+# Enable sending and receiving NTP over PTP packets (PTP transport)
+ptpport {{ ptp.port }}
+{% endif %}
diff --git a/data/templates/conntrack/nftables-ct.j2 b/data/templates/conntrack/nftables-ct.j2
index c753e6bcb..0f0c49c76 100644
--- a/data/templates/conntrack/nftables-ct.j2
+++ b/data/templates/conntrack/nftables-ct.j2
@@ -16,32 +16,41 @@ table ip vyos_conntrack {
{% endif %}
return
}
- chain VYOS_CT_TIMEOUT {
{% if timeout.custom.ipv4.rule is vyos_defined %}
+ chain VYOS_CT_TIMEOUT {
{% for rule, rule_config in timeout.custom.ipv4.rule.items() %}
# rule-{{ rule }} {{ '- ' ~ rule_config.description if rule_config.description is vyos_defined }}
{{ rule_config | conntrack_rule(rule, 'timeout', ipv6=False) }}
{% endfor %}
-{% endif %}
return
}
-{% if timeout.custom.ipv4.rule is vyos_defined %}
{% for rule, rule_config in timeout.custom.ipv4.rule.items() %}
ct timeout ct-timeout-{{ rule }} {
l3proto ip;
{% for protocol, protocol_config in rule_config.protocol.items() %}
protocol {{ protocol }};
+{% if protocol_config | count > 0 %}
policy = { {{ protocol_config | conntrack_ct_policy() }} }
+{% endif %}
{% endfor %}
}
{% endfor %}
+
+ chain PREROUTING_CT_TIMEOUT {
+ type filter hook prerouting priority -199; policy accept;
+ counter jump VYOS_CT_TIMEOUT
+ }
+
+ chain OUTPUT_CT_TIMEOUT {
+ type filter hook output priority -199; policy accept;
+ counter jump VYOS_CT_TIMEOUT
+ }
{% endif %}
chain PREROUTING {
type filter hook prerouting priority -300; policy accept;
counter jump VYOS_CT_IGNORE
- counter jump VYOS_CT_TIMEOUT
counter jump FW_CONNTRACK
counter jump NAT_CONNTRACK
counter jump WLB_CONNTRACK
@@ -58,7 +67,6 @@ table ip vyos_conntrack {
chain OUTPUT {
type filter hook output priority -300; policy accept;
counter jump VYOS_CT_IGNORE
- counter jump VYOS_CT_TIMEOUT
counter jump FW_CONNTRACK
counter jump NAT_CONNTRACK
{% if wlb_local_action %}
@@ -106,32 +114,41 @@ table ip6 vyos_conntrack {
{% endif %}
return
}
- chain VYOS_CT_TIMEOUT {
{% if timeout.custom.ipv6.rule is vyos_defined %}
+ chain VYOS_CT_TIMEOUT {
{% for rule, rule_config in timeout.custom.ipv6.rule.items() %}
# rule-{{ rule }} {{ '- ' ~ rule_config.description if rule_config.description is vyos_defined }}
{{ rule_config | conntrack_rule(rule, 'timeout', ipv6=True) }}
{% endfor %}
-{% endif %}
return
}
-{% if timeout.custom.ipv6.rule is vyos_defined %}
{% for rule, rule_config in timeout.custom.ipv6.rule.items() %}
ct timeout ct-timeout-{{ rule }} {
l3proto ip;
{% for protocol, protocol_config in rule_config.protocol.items() %}
protocol {{ protocol }};
+{% if protocol_config | count > 0 %}
policy = { {{ protocol_config | conntrack_ct_policy() }} }
+{% endif %}
{% endfor %}
}
{% endfor %}
+
+ chain PREROUTING_CT_TIMEOUT {
+ type filter hook prerouting priority -199; policy accept;
+ counter jump VYOS_CT_TIMEOUT
+ }
+
+ chain OUTPUT_CT_TIMEOUT {
+ type filter hook output priority -199; policy accept;
+ counter jump VYOS_CT_TIMEOUT
+ }
{% endif %}
chain PREROUTING {
type filter hook prerouting priority -300; policy accept;
counter jump VYOS_CT_IGNORE
- counter jump VYOS_CT_TIMEOUT
counter jump FW_CONNTRACK
counter jump NAT_CONNTRACK
notrack
@@ -147,7 +164,6 @@ table ip6 vyos_conntrack {
chain OUTPUT {
type filter hook output priority -300; policy accept;
counter jump VYOS_CT_IGNORE
- counter jump VYOS_CT_TIMEOUT
counter jump FW_CONNTRACK
counter jump NAT_CONNTRACK
notrack
diff --git a/data/templates/conntrack/sysctl.conf.j2 b/data/templates/conntrack/sysctl.conf.j2
index cd6c34ede..8d934db9c 100644
--- a/data/templates/conntrack/sysctl.conf.j2
+++ b/data/templates/conntrack/sysctl.conf.j2
@@ -1,10 +1,11 @@
# Autogenerated by system_conntrack.py
{# all values have defaults - thus no checking required #}
+net.netfilter.nf_conntrack_buckets = {{ hash_size }}
net.netfilter.nf_conntrack_expect_max = {{ expect_table_size }}
net.netfilter.nf_conntrack_max = {{ table_size }}
net.ipv4.tcp_max_syn_backlog = {{ tcp.half_open_connections }}
net.netfilter.nf_conntrack_tcp_loose = {{ '1' if tcp.loose is vyos_defined('enable') else '0' }}
net.netfilter.nf_conntrack_tcp_max_retrans = {{ tcp.max_retrans }}
net.netfilter.nf_conntrack_acct = {{ '1' if flow_accounting is vyos_defined else '0' }}
-net.netfilter.nf_conntrack_timestamp = {{ '1' if log.timestamp is vyos_defined else '0' }} \ No newline at end of file
+net.netfilter.nf_conntrack_timestamp = {{ '1' if log.timestamp is vyos_defined else '0' }}
diff --git a/data/templates/conntrack/vyos_nf_conntrack.conf.j2 b/data/templates/conntrack/vyos_nf_conntrack.conf.j2
deleted file mode 100644
index 1b12fec5f..000000000
--- a/data/templates/conntrack/vyos_nf_conntrack.conf.j2
+++ /dev/null
@@ -1,2 +0,0 @@
-# Autogenerated by system_conntrack.py
-options nf_conntrack hashsize={{ hash_size }}
diff --git a/data/templates/conntrackd/conntrackd.conf.j2 b/data/templates/conntrackd/conntrackd.conf.j2
index 30e619daf..d662f1262 100644
--- a/data/templates/conntrackd/conntrackd.conf.j2
+++ b/data/templates/conntrackd/conntrackd.conf.j2
@@ -3,6 +3,7 @@
# Synchronizer settings
Sync {
Mode FTFW {
+ PurgeTimeout {{ purge_timeout }}
DisableExternalCache {{ 'on' if disable_external_cache is vyos_defined else 'off' }}
StartupResync {{ 'on' if startup_resync is vyos_defined else 'off' }}
}
diff --git a/data/templates/conserver/dropbear@.service.j2 b/data/templates/conserver/dropbear@.service.j2
index e355dab43..c6c31f98f 100644
--- a/data/templates/conserver/dropbear@.service.j2
+++ b/data/templates/conserver/dropbear@.service.j2
@@ -1,4 +1,4 @@
[Service]
ExecStart=
-ExecStart=/usr/sbin/dropbear -w -j -k -r /etc/dropbear/dropbear_rsa_host_key -b /etc/issue.net -c "/usr/bin/console {{ device }}" -P /run/conserver/dropbear.%I.pid -p %I
+ExecStart=/usr/sbin/dropbear -w -j -k -r /etc/dropbear/dropbear_rsa_host_key -r /etc/dropbear/dropbear_ecdsa_host_key -b /etc/issue.net -c "/usr/bin/console {{ device }}" -P /run/conserver/dropbear.%I.pid -p %I
PIDFile=/run/conserver/dropbear.%I.pid
diff --git a/data/templates/container/containers.conf.j2 b/data/templates/container/containers.conf.j2
index c8b54dfbb..414c3e849 100644
--- a/data/templates/container/containers.conf.j2
+++ b/data/templates/container/containers.conf.j2
@@ -170,10 +170,6 @@ default_sysctls = [
#
#label = true
-# Logging driver for the container. Available options: k8s-file and journald.
-#
-#log_driver = "k8s-file"
-
# Maximum size allowed for the container log file. Negative numbers indicate
# that no size limit is imposed. If positive, it must be >= 8192 to match or
# exceed conmon's read buffer. The file is truncated and re-opened so the
diff --git a/data/templates/container/registries.conf.j2 b/data/templates/container/registries.conf.j2
index eb7ff8775..b5c7eed9b 100644
--- a/data/templates/container/registries.conf.j2
+++ b/data/templates/container/registries.conf.j2
@@ -28,4 +28,14 @@
{% set _ = registry_list.append(r) %}
{% endfor %}
unqualified-search-registries = {{ registry_list }}
+{% for r, r_options in registry.items() if r_options.disable is not vyos_defined %}
+[[registry]]
+{% if r_options.mirror is vyos_defined %}
+location = "{{ r_options.mirror.host_name if r_options.mirror.host_name is vyos_defined else r_options.mirror.address }}{{ ":" + r_options.mirror.port if r_options.mirror.port is vyos_defined }}{{ r_options.mirror.path if r_options.mirror.path is vyos_defined }}"
+{% else %}
+location = "{{ r }}"
+{% endif %}
+insecure = {{ 'true' if r_options.insecure is vyos_defined else 'false' }}
+prefix = "{{ r }}"
+{% endfor %}
{% endif %}
diff --git a/data/templates/dhcp-client/ipv6.j2 b/data/templates/dhcp-client/ipv6.j2
index 311c856c8..07faeb91c 100644
--- a/data/templates/dhcp-client/ipv6.j2
+++ b/data/templates/dhcp-client/ipv6.j2
@@ -6,8 +6,12 @@ interface {{ ifname }} {
send client-id {{ dhcpv6_options.duid }};
{% endif %}
{% if address is vyos_defined and 'dhcpv6' in address %}
+{% if dhcpv6_options.no_request_dns is not vyos_defined %}
request domain-name-servers;
+{% endif %}
+{% if dhcpv6_options.no_request_domain_name is not vyos_defined %}
request domain-name;
+{% endif %}
{% if dhcpv6_options.parameters_only is vyos_defined %}
information-only;
{% endif %}
@@ -39,12 +43,10 @@ id-assoc na 0 {
id-assoc pd {{ pd }} {
{# length got a default value #}
prefix ::/{{ pd_config.length }} infinity;
-{% set sla_len = 64 - pd_config.length | int %}
{% set count = namespace(value=0) %}
{% if pd_config.interface is vyos_defined %}
{% for interface, interface_config in pd_config.interface.items() if pd_config.interface is vyos_defined %}
prefix-interface {{ interface }} {
- sla-len {{ sla_len }};
{% if interface_config.sla_id is vyos_defined %}
sla-id {{ interface_config.sla_id }};
{% else %}
diff --git a/data/templates/dhcp-client/ipv6.override.conf.j2 b/data/templates/dhcp-client/ipv6.override.conf.j2
index b0c0e0544..d270a55fc 100644
--- a/data/templates/dhcp-client/ipv6.override.conf.j2
+++ b/data/templates/dhcp-client/ipv6.override.conf.j2
@@ -4,6 +4,9 @@
[Unit]
ConditionPathExists={{ dhcp6_client_dir }}/dhcp6c.%i.conf
+{% if ifname.startswith('pppoe') %}
+After=ppp@{{ ifname }}.service
+{% endif %}
[Service]
ExecStart=
diff --git a/data/templates/dhcp-server/10-override.conf.j2 b/data/templates/dhcp-server/10-override.conf.j2
deleted file mode 100644
index 6cf9e0a11..000000000
--- a/data/templates/dhcp-server/10-override.conf.j2
+++ /dev/null
@@ -1,2 +0,0 @@
-[Unit]
-ConditionFileNotEmpty=
diff --git a/data/templates/dhcp-server/kea-ctrl-agent.conf.j2 b/data/templates/dhcp-server/kea-ctrl-agent.conf.j2
deleted file mode 100644
index b37cf4798..000000000
--- a/data/templates/dhcp-server/kea-ctrl-agent.conf.j2
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "Control-agent": {
-{% if high_availability is vyos_defined %}
- "http-host": "{{ high_availability.source_address }}",
- "http-port": 647,
- "control-sockets": {
- "dhcp4": {
- "socket-type": "unix",
- "socket-name": "/run/kea/dhcp4-ctrl-socket"
- }
- }
-{% endif %}
- }
-}
diff --git a/data/templates/dhcp-server/kea-dhcp-ddns.conf.j2 b/data/templates/dhcp-server/kea-dhcp-ddns.conf.j2
new file mode 100644
index 000000000..632b38fd8
--- /dev/null
+++ b/data/templates/dhcp-server/kea-dhcp-ddns.conf.j2
@@ -0,0 +1,35 @@
+{
+ "DhcpDdns": {
+ "ip-address": "127.0.0.1",
+ "port": 53001,
+ "control-socket": {
+{% if vrf_context is vyos_defined %}
+ "socket-type": "unix",
+ "socket-name": "/var/run/kea/kea-ddns-{{ vrf_context }}-ctrl-socket"
+{% else %}
+ "socket-type": "unix",
+ "socket-name": "/var/run/kea/kea-ddns-ctrl-socket"
+{% endif %}
+ },
+ "tsig-keys": {{ dynamic_dns_update | kea_dynamic_dns_update_tsig_key_json }},
+ "forward-ddns" : {
+ "ddns-domains": {{ dynamic_dns_update | kea_dynamic_dns_update_domains('forward_domain') }}
+ },
+ "reverse-ddns" : {
+ "ddns-domains": {{ dynamic_dns_update | kea_dynamic_dns_update_domains('reverse_domain') }}
+ },
+ "loggers": [
+ {
+ "name": "kea-dhcp-ddns",
+ "output_options": [
+ {
+ "output": "stdout",
+ "pattern": "%-5p %m\n"
+ }
+ ],
+ "severity": "{{ log_level | upper }}",
+ "debuglevel": 0
+ }
+ ]
+ }
+}
diff --git a/data/templates/dhcp-server/kea-dhcp4.conf.j2 b/data/templates/dhcp-server/kea-dhcp4.conf.j2
index bf37b94f6..75be63ccb 100644
--- a/data/templates/dhcp-server/kea-dhcp4.conf.j2
+++ b/data/templates/dhcp-server/kea-dhcp4.conf.j2
@@ -11,45 +11,55 @@
"interfaces": [ "*" ],
"dhcp-socket-type": "raw",
{% endif %}
- "service-sockets-max-retries": 5,
+ "service-sockets-max-retries": 60,
"service-sockets-retry-wait-time": 5000
},
"control-socket": {
+{% if vrf_context is vyos_defined %}
"socket-type": "unix",
- "socket-name": "/run/kea/dhcp4-ctrl-socket"
+ "socket-name": "/var/run/kea/dhcp4-{{ vrf_context }}-ctrl-socket"
+{% else %}
+ "socket-type": "unix",
+ "socket-name": "/var/run/kea/dhcp4-ctrl-socket"
+{% endif %}
},
"lease-database": {
"type": "memfile",
"persist": true,
"name": "{{ lease_file }}"
},
+ "multi-threading": {
+ "enable-multi-threading": true
+ },
+{% if client_class is vyos_defined %}
+ "client-classes": {{ client_class | kea_client_class_json }},
+{% endif %}
"option-def": [
{
- "name": "rfc3442-static-route",
- "code": 121,
- "type": "record",
- "array": true,
- "record-types": "uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8"
- },
- {
- "name": "windows-static-route",
- "code": 249,
- "type": "record",
- "array": true,
- "record-types": "uint8,uint8,uint8,uint8,uint8,uint8,uint8,uint8"
- },
- {
"name": "wpad-url",
"code": 252,
"type": "string"
},
{
- "name": "unifi-controller",
+ "name": "ubnt",
"code": 1,
"type": "ipv4-address",
- "space": "ubnt"
+ "space": "vendor-encapsulated-options-space"
}
],
+{% if dynamic_dns_update is vyos_defined %}
+ "dhcp-ddns": {
+ "enable-updates": true,
+ "server-ip": "127.0.0.1",
+ "server-port": 53001,
+ "sender-ip": "",
+ "sender-port": 0,
+ "max-queue-size": 1024,
+ "ncr-protocol": "UDP",
+ "ncr-format": "JSON"
+ },
+ {{ dynamic_dns_update | kea_dynamic_dns_update_main_json }}
+{% endif %}
"hooks-libraries": [
{% if high_availability is vyos_defined %}
{
@@ -68,13 +78,38 @@
}
},
{% endif %}
+{% if any_ping_check is vyos_defined %}
+ {
+ "library": "/usr/lib/{{ machine }}-linux-gnu/kea/hooks/libdhcp_ping_check.so",
+ "parameters": {
+ "enable-ping-check" : true,
+ "min-ping-requests" : 1,
+ "reply-timeout" : 100,
+ "ping-cltt-secs" : 60,
+ "ping-channel-threads" : 0
+ }
+ },
+{% endif %}
{
"library": "/usr/lib/{{ machine }}-linux-gnu/kea/hooks/libdhcp_lease_cmds.so",
"parameters": {}
}
],
{% if shared_network_name is vyos_defined %}
- "shared-networks": {{ shared_network_name | kea_shared_network_json }}
+ "shared-networks": {{ shared_network_name | kea_shared_network_json }},
{% endif %}
+ "loggers": [
+ {
+ "name": "kea-dhcp4",
+ "output_options": [
+ {
+ "output": "stdout",
+ "pattern": "%-5p %m\n"
+ }
+ ],
+ "severity": "{{ log_level | upper }}",
+ "debuglevel": 0
+ }
+ ]
}
}
diff --git a/data/templates/dhcp-server/kea-dhcp6.conf.j2 b/data/templates/dhcp-server/kea-dhcp6.conf.j2
index 2f0de6b30..6b4d1d5b0 100644
--- a/data/templates/dhcp-server/kea-dhcp6.conf.j2
+++ b/data/templates/dhcp-server/kea-dhcp6.conf.j2
@@ -6,12 +6,17 @@
{% else %}
"interfaces": [ "*" ],
{% endif %}
- "service-sockets-max-retries": 5,
+ "service-sockets-max-retries": 60,
"service-sockets-retry-wait-time": 5000
},
"control-socket": {
+{% if vrf_context is vyos_defined %}
"socket-type": "unix",
- "socket-name": "/run/kea/dhcp6-ctrl-socket"
+ "socket-name": "/var/run/kea/dhcp6-{{ vrf_context }}-ctrl-socket"
+{% else %}
+ "socket-type": "unix",
+ "socket-name": "/var/run/kea/dhcp6-ctrl-socket"
+{% endif %}
},
"lease-database": {
"type": "memfile",
@@ -54,8 +59,20 @@
{% endif %}
],
{% if shared_network_name is vyos_defined %}
- "shared-networks": {{ shared_network_name | kea6_shared_network_json }}
+ "shared-networks": {{ shared_network_name | kea6_shared_network_json }},
{% endif %}
-
+ "loggers": [
+ {
+ "name": "kea-dhcp6",
+ "output_options": [
+ {
+ "output": "stdout",
+ "pattern": "%-5p %m\n"
+ }
+ ],
+ "severity": "{{ log_level | upper }}",
+ "debuglevel": 0
+ }
+ ]
}
}
diff --git a/data/templates/dns-dynamic/ddclient.conf.j2 b/data/templates/dns-dynamic/ddclient.conf.j2
index 5538ea56c..b209c8c81 100644
--- a/data/templates/dns-dynamic/ddclient.conf.j2
+++ b/data/templates/dns-dynamic/ddclient.conf.j2
@@ -21,11 +21,7 @@ if{{ ipv }}={{ address }}, \
{{ host }}
{% endmacro %}
### Autogenerated by service_dns_dynamic.py ###
-daemon={{ interval }}
-syslog=yes
ssl=yes
-pid={{ config_file | replace('.conf', '.pid') }}
-cache={{ config_file | replace('.conf', '.cache') }}
{# ddclient default (web=dyndns) doesn't support ssl and results in process lockup #}
web=googledomains
{# ddclient default (use=ip) results in confusing warning message in log #}
diff --git a/data/templates/dns-dynamic/override.conf.j2 b/data/templates/dns-dynamic/override.conf.j2
index 4a6851cef..aaed4ff35 100644
--- a/data/templates/dns-dynamic/override.conf.j2
+++ b/data/templates/dns-dynamic/override.conf.j2
@@ -1,10 +1,12 @@
{% set vrf_command = 'ip vrf exec ' ~ vrf ~ ' ' if vrf is vyos_defined else '' %}
+{% set cache_file = config_file.replace('.conf', '.cache') %}
[Unit]
ConditionPathExists={{ config_file }}
+Wants=
After=vyos-router.service
[Service]
-PIDFile={{ config_file | replace('.conf', '.pid') }}
EnvironmentFile=
ExecStart=
-ExecStart={{ vrf_command }}/usr/bin/ddclient -file {{ config_file }}
+ExecStart={{ vrf_command }}/usr/bin/ddclient --file {{ config_file }} --cache {{ cache_file }} --foreground --daemon {{ interval }}
+Restart=always
diff --git a/data/templates/firewall/nftables-bridge.j2 b/data/templates/firewall/nftables-bridge.j2
index 1975fb9b0..9821183cd 100644
--- a/data/templates/firewall/nftables-bridge.j2
+++ b/data/templates/firewall/nftables-bridge.j2
@@ -43,7 +43,7 @@
{% if bridge.output is vyos_defined %}
{% for prior, conf in bridge.output.items() %}
- chain VYOS_OUTUT_{{ prior }} {
+ chain VYOS_OUTPUT_{{ prior }} {
type filter hook output priority {{ prior }}; policy accept;
{% if global_options.state_policy is vyos_defined %}
jump VYOS_STATE_POLICY
diff --git a/data/templates/firewall/nftables-defines.j2 b/data/templates/firewall/nftables-defines.j2
index fa6cd74c0..c4b6b7eba 100644
--- a/data/templates/firewall/nftables-defines.j2
+++ b/data/templates/firewall/nftables-defines.j2
@@ -35,6 +35,24 @@
}
{% endfor %}
{% endif %}
+{% if group.remote_group is vyos_defined and is_l3 and not is_ipv6 %}
+{% for name, name_config in group.remote_group.items() %}
+ set R_{{ name }} {
+ type {{ ip_type }}
+ flags interval
+ auto-merge
+ }
+{% endfor %}
+{% endif %}
+{% if group.remote_group is vyos_defined and is_l3 and is_ipv6 %}
+{% for name, name_config in group.remote_group.items() %}
+ set R6_{{ name }} {
+ type {{ ip_type }}
+ flags interval
+ auto-merge
+ }
+{% endfor %}
+{% endif %}
{% if group.mac_group is vyos_defined %}
{% for group_name, group_conf in group.mac_group.items() %}
{% set includes = group_conf.include if group_conf.include is vyos_defined else [] %}
@@ -93,7 +111,7 @@
flags interval
auto-merge
{% if group_conf.interface is vyos_defined or includes %}
- elements = { {{ group_conf.interface | nft_nested_group(includes, group.interface_group, 'interface') | join(",") }} }
+ elements = { {{ group_conf.interface | nft_nested_group(includes, group.interface_group, 'interface') | quoted_join(",") }} }
{% endif %}
}
{% endfor %}
diff --git a/data/templates/firewall/nftables-geoip-update.j2 b/data/templates/firewall/nftables-geoip-update.j2
index 832ccc3e9..c51e4aafc 100644
--- a/data/templates/firewall/nftables-geoip-update.j2
+++ b/data/templates/firewall/nftables-geoip-update.j2
@@ -1,12 +1,12 @@
#!/usr/sbin/nft -f
-{% if ipv4_sets is vyos_defined %}
-{% for setname, ip_list in ipv4_sets.items() %}
+{% if firewall_sets.v4 is vyos_defined %}
+{% for setname, ip_list in firewall_sets.v4.items() %}
flush set ip vyos_filter {{ setname }}
{% endfor %}
table ip vyos_filter {
-{% for setname, ip_list in ipv4_sets.items() %}
+{% for setname, ip_list in firewall_sets.v4.items() %}
set {{ setname }} {
type ipv4_addr
flags interval
@@ -16,13 +16,46 @@ table ip vyos_filter {
}
{% endif %}
-{% if ipv6_sets is vyos_defined %}
-{% for setname, ip_list in ipv6_sets.items() %}
+{% if firewall_sets.v6 is vyos_defined %}
+{% for setname, ip_list in firewall_sets.v6.items() %}
flush set ip6 vyos_filter {{ setname }}
{% endfor %}
table ip6 vyos_filter {
-{% for setname, ip_list in ipv6_sets.items() %}
+{% for setname, ip_list in firewall_sets.v6.items() %}
+ set {{ setname }} {
+ type ipv6_addr
+ flags interval
+ elements = { {{ ','.join(ip_list) }} }
+ }
+{% endfor %}
+}
+{% endif %}
+
+
+{% if policy_sets.v4 is vyos_defined %}
+{% for setname, ip_list in policy_sets.v4.items() %}
+flush set ip vyos_mangle {{ setname }}
+{% endfor %}
+
+table ip vyos_mangle {
+{% for setname, ip_list in policy_sets.v4.items() %}
+ set {{ setname }} {
+ type ipv4_addr
+ flags interval
+ elements = { {{ ','.join(ip_list) }} }
+ }
+{% endfor %}
+}
+{% endif %}
+
+{% if policy_sets.v6 is vyos_defined %}
+{% for setname, ip_list in policy_sets.v6.items() %}
+flush set ip6 vyos_mangle {{ setname }}
+{% endfor %}
+
+table ip6 vyos_mangle {
+{% for setname, ip_list in policy_sets.v6.items() %}
set {{ setname }} {
type ipv6_addr
flags interval
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/firewall/nftables-policy.j2 b/data/templates/firewall/nftables-policy.j2
index 9e28899b0..68f79e656 100644
--- a/data/templates/firewall/nftables-policy.j2
+++ b/data/templates/firewall/nftables-policy.j2
@@ -33,6 +33,15 @@ table ip vyos_mangle {
{% endif %}
}
{% endfor %}
+
+{% if geoip_sets.name is vyos_defined %}
+{% for setname in geoip_sets.name %}
+ set {{ setname }} {
+ type ipv4_addr
+ flags interval
+ }
+{% endfor %}
+{% endif %}
{% endif %}
{{ group_tmpl.groups(firewall_group, False, True) }}
@@ -65,6 +74,14 @@ table ip6 vyos_mangle {
{% endif %}
}
{% endfor %}
+{% if geoip_sets.ipv6_name is vyos_defined %}
+{% for setname in geoip_sets.ipv6_name %}
+ set {{ setname }} {
+ type ipv6_addr
+ flags interval
+ }
+{% endfor %}
+{% endif %}
{% endif %}
{{ group_tmpl.groups(firewall_group, True, True) }}
diff --git a/data/templates/firewall/nftables-zone.j2 b/data/templates/firewall/nftables-zone.j2
index e78725079..7b4128082 100644
--- a/data/templates/firewall/nftables-zone.j2
+++ b/data/templates/firewall/nftables-zone.j2
@@ -8,7 +8,12 @@
{% endif %}
{% for zone_name, zone_conf in zone.items() %}
{% if 'local_zone' not in zone_conf %}
- oifname { {{ zone_conf.interface | join(',') }} } counter jump VZONE_{{ zone_name }}
+{% if 'interface' in zone_conf.member %}
+ oifname { {{ zone_conf.member.interface | quoted_join(',') }} } counter jump VZONE_{{ zone_name }}
+{% endif %}
+{% if 'vrf' in zone_conf.member %}
+ oifname { {{ zone_conf.member.vrf | quoted_join(",") }} } counter jump VZONE_{{ zone_name }}
+{% endif %}
{% endif %}
{% endfor %}
}
@@ -40,38 +45,89 @@
iifname lo counter return
{% if zone_conf.from is vyos_defined %}
{% for from_zone, from_conf in zone_conf.from.items() if from_conf.firewall[fw_name] is vyos_defined %}
- iifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf.firewall[fw_name] }}
- iifname { {{ zone[from_zone].interface | join(",") }} } counter return
+
+{% if 'interface' in zone[from_zone].member %}
+ iifname { {{ zone[from_zone].member.interface | quoted_join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf.firewall[fw_name] }}
+ iifname { {{ zone[from_zone].member.interface | quoted_join(",") }} } counter return
+{% endif %}
+{% if 'vrf' in zone[from_zone].member %}
+ iifname { {{ zone[from_zone].member.vrf | quoted_join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf.firewall[fw_name] }}
+ iifname { {{ zone[from_zone].member.vrf | quoted_join(",") }} } counter return
+{% endif %}
{% endfor %}
{% endif %}
+{% if zone_conf.default_firewall is vyos_defined and zone_conf.default_firewall[fw_name] is vyos_defined %}
+ counter jump NAME{{ suffix }}_{{ zone_conf.default_firewall[fw_name] }}
+ counter return
+{% endif %}
{{ zone_conf | nft_default_rule('zone_' + zone_name, family) }}
}
chain VZONE_{{ zone_name }}_OUT {
oifname lo counter return
{% if zone_conf.from_local is vyos_defined %}
{% for from_zone, from_conf in zone_conf.from_local.items() if from_conf.firewall[fw_name] is vyos_defined %}
- oifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf.firewall[fw_name] }}
- oifname { {{ zone[from_zone].interface | join(",") }} } counter return
+{% if 'interface' in zone[from_zone].member %}
+ oifname { {{ zone[from_zone].member.interface | quoted_join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf.firewall[fw_name] }}
+ oifname { {{ zone[from_zone].member.interface | quoted_join(",") }} } counter return
+{% endif %}
+{% if 'vrf' in zone[from_zone].member %}
+ oifname { {{ zone[from_zone].member.vrf | quoted_join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf.firewall[fw_name] }}
+ oifname { {{ zone[from_zone].member.vrf | quoted_join(",") }} } counter return
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if zone_conf.default_local is vyos_defined %}
+{% for from_zone, from_conf in zone_conf.default_local.items() if from_conf[fw_name] is vyos_defined %}
+{% if 'interface' in zone[from_zone].member %}
+ oifname { {{ zone[from_zone].member.interface | quoted_join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf[fw_name] }}
+ oifname { {{ zone[from_zone].member.interface | quoted_join(",") }} } counter return
+{% endif %}
+{% if 'vrf' in zone[from_zone].member %}
+{% for vrf_name in zone[from_zone].member.vrf %}
+ oifname { "{{ zone[from_zone]['vrf_interfaces'][vrf_name] }}" } counter jump NAME{{ suffix }}_{{ from_conf[fw_name] }}
+ oifname { "{{ zone[from_zone]['vrf_interfaces'][vrf_name] }}" } counter return
+{% endfor %}
+{% endif %}
{% endfor %}
{% endif %}
{{ zone_conf | nft_default_rule('zone_' + zone_name, family) }}
}
{% else %}
chain VZONE_{{ zone_name }} {
- iifname { {{ zone_conf.interface | join(",") }} } counter {{ zone_conf | nft_intra_zone_action(ipv6) }}
+{% if 'interface' in zone_conf.member %}
+ iifname { {{ zone_conf.member.interface | quoted_join(",") }} } counter {{ zone_conf | nft_intra_zone_action(ipv6) }}
+{% endif %}
+{% if 'vrf' in zone_conf.member %}
+ iifname { {{ zone_conf.member.vrf | quoted_join(",") }} } counter {{ zone_conf | nft_intra_zone_action(ipv6) }}
+{% endif %}
{% if zone_conf.intra_zone_filtering is vyos_defined %}
- iifname { {{ zone_conf.interface | join(",") }} } counter return
+{% if 'interface' in zone_conf.member %}
+ iifname { {{ zone_conf.member.interface | quoted_join(",") }} } counter return
+{% endif %}
+{% if 'vrf' in zone_conf.member %}
+ iifname { {{ zone_conf.member.vrf | quoted_join(",") }} } counter return
+{% endif %}
{% endif %}
{% if zone_conf.from is vyos_defined %}
{% for from_zone, from_conf in zone_conf.from.items() if from_conf.firewall[fw_name] is vyos_defined %}
{% if zone[from_zone].local_zone is not defined %}
- iifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf.firewall[fw_name] }}
- iifname { {{ zone[from_zone].interface | join(",") }} } counter return
+{% if 'interface' in zone[from_zone].member %}
+ iifname { {{ zone[from_zone].member.interface | quoted_join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf.firewall[fw_name] }}
+ iifname { {{ zone[from_zone].member.interface | quoted_join(",") }} } counter return
+{% endif %}
+{% if 'vrf' in zone[from_zone].member %}
+ iifname { {{ zone[from_zone].member.vrf | quoted_join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf.firewall[fw_name] }}
+ iifname { {{ zone[from_zone].member.vrf | quoted_join(",") }} } counter return
+{% endif %}
{% endif %}
{% endfor %}
{% endif %}
+{% if zone_conf.default_firewall is vyos_defined and zone_conf.default_firewall[fw_name] is vyos_defined %}
+ counter jump NAME{{ suffix }}_{{ zone_conf.default_firewall[fw_name] }}
+ counter return
+{% endif %}
{{ zone_conf | nft_default_rule('zone_' + zone_name, family) }}
}
{% endif %}
{% endfor %}
-{% endmacro %} \ No newline at end of file
+{% endmacro %}
diff --git a/data/templates/firewall/nftables.j2 b/data/templates/firewall/nftables.j2
index 034328400..e3d5b20e8 100755
--- a/data/templates/firewall/nftables.j2
+++ b/data/templates/firewall/nftables.j2
@@ -47,7 +47,7 @@ table ip vyos_filter {
chain VYOS_FORWARD_{{ prior }} {
type filter hook forward priority {{ prior }}; policy accept;
{% if global_options.state_policy is vyos_defined %}
- jump VYOS_STATE_POLICY
+ jump VYOS_STATE_POLICY_FORWARD
{% endif %}
{% if conf.rule is vyos_defined %}
{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
@@ -140,6 +140,25 @@ table ip vyos_filter {
{% endfor %}
{% endif %}
+{% if ipv4.forward.filter.disable_conntrack is vyos_defined or ipv4.input.filter.disable_conntrack is vyos_defined %}
+ chain VYOS_DISABLE_CONNTRACK_INP_FWD {
+ type filter hook prerouting priority -320; policy accept;
+{% if ipv4.forward.filter.disable_conntrack is vyos_defined %}
+ fib daddr . iif type unicast notrack counter comment "DISABLE-CT-FWD"
+{% endif %}
+{% if ipv4.input.filter.disable_conntrack is vyos_defined %}
+ fib daddr . iif type local notrack counter comment "DISABLE-CT-INP"
+{% endif %}
+ }
+{% endif %}
+
+{% if ipv4.output.filter.disable_conntrack is vyos_defined %}
+ chain VYOS_DISABLE_CONNTRACK_OUT {
+ type filter hook output priority -320; policy accept;
+ notrack counter comment "DISABLE-CT-OUT"
+ }
+{% endif %}
+
{% for set_name in ns.sets %}
set RECENT_{{ set_name }} {
type ipv4_addr
@@ -153,8 +172,8 @@ table ip vyos_filter {
flags interval
}
{% endfor %}
-{% if geoip_updated.name is vyos_defined %}
-{% for setname in geoip_updated.name %}
+{% if geoip_sets.name is vyos_defined %}
+{% for setname in geoip_sets.name %}
set {{ setname }} {
type ipv4_addr
flags interval
@@ -180,6 +199,22 @@ table ip vyos_filter {
{% endif %}
return
}
+
+ chain VYOS_STATE_POLICY_FORWARD {
+{% if global_options.state_policy.offload is vyos_defined %}
+ counter flow add @VYOS_FLOWTABLE_{{ global_options.state_policy.offload.offload_target }}
+{% endif %}
+{% if global_options.state_policy.established is vyos_defined %}
+ {{ global_options.state_policy.established | nft_state_policy('established') }}
+{% endif %}
+{% if global_options.state_policy.invalid is vyos_defined %}
+ {{ global_options.state_policy.invalid | nft_state_policy('invalid') }}
+{% endif %}
+{% if global_options.state_policy.related is vyos_defined %}
+ {{ global_options.state_policy.related | nft_state_policy('related') }}
+{% endif %}
+ return
+ }
{% endif %}
}
@@ -200,7 +235,7 @@ table ip6 vyos_filter {
chain VYOS_IPV6_FORWARD_{{ prior }} {
type filter hook forward priority {{ prior }}; policy accept;
{% if global_options.state_policy is vyos_defined %}
- jump VYOS_STATE_POLICY6
+ jump VYOS_STATE_POLICY6_FORWARD
{% endif %}
{% if conf.rule is vyos_defined %}
{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
@@ -246,7 +281,7 @@ table ip6 vyos_filter {
{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
{{ rule_conf | nft_rule('OUT', prior, rule_id, 'ip6') }}
{% if rule_conf.recent is vyos_defined %}
-{% set ns.sets = ns.sets + ['OUT_ ' + prior + '_' + rule_id] %}
+{% set ns.sets = ns.sets + ['OUT_' + prior + '_' + rule_id] %}
{% endif %}
{% endfor %}
{% endif %}
@@ -292,6 +327,25 @@ table ip6 vyos_filter {
{% endfor %}
{% endif %}
+{% if ipv6.forward.filter.disable_conntrack is vyos_defined or ipv6.input.filter.disable_conntrack is vyos_defined %}
+ chain VYOS_DISABLE_CONNTRACK_INP_FWD_V6 {
+ type filter hook prerouting priority -320; policy accept;
+{% if ipv6.forward.filter.disable_conntrack is vyos_defined %}
+ fib daddr . iif type unicast notrack counter comment "DISABLE-CT-FWD-V6"
+{% endif %}
+{% if ipv6.input.filter.disable_conntrack is vyos_defined %}
+ fib daddr . iif type local notrack counter comment "DISABLE-CT-INP-V6"
+{% endif %}
+ }
+{% endif %}
+
+{% if ipv6.output.filter.disable_conntrack is vyos_defined %}
+ chain VYOS_DISABLE_CONNTRACK_OUT_V6 {
+ type filter hook output priority -320; policy accept;
+ notrack counter comment "DISABLE-CT-OUT-V6"
+ }
+{% endif %}
+
{% for set_name in ns.sets %}
set RECENT6_{{ set_name }} {
type ipv6_addr
@@ -305,8 +359,8 @@ table ip6 vyos_filter {
flags interval
}
{% endfor %}
-{% if geoip_updated.ipv6_name is vyos_defined %}
-{% for setname in geoip_updated.ipv6_name %}
+{% if geoip_sets.ipv6_name is vyos_defined %}
+{% for setname in geoip_sets.ipv6_name %}
set {{ setname }} {
type ipv6_addr
flags interval
@@ -331,6 +385,22 @@ table ip6 vyos_filter {
{% endif %}
return
}
+
+ chain VYOS_STATE_POLICY6_FORWARD {
+{% if global_options.state_policy.offload is vyos_defined %}
+ counter flow add @VYOS_FLOWTABLE_{{ global_options.state_policy.offload.offload_target }}
+{% endif %}
+{% if global_options.state_policy.established is vyos_defined %}
+ {{ global_options.state_policy.established | nft_state_policy('established') }}
+{% endif %}
+{% if global_options.state_policy.invalid is vyos_defined %}
+ {{ global_options.state_policy.invalid | nft_state_policy('invalid') }}
+{% endif %}
+{% if global_options.state_policy.related is vyos_defined %}
+ {{ global_options.state_policy.related | nft_state_policy('related') }}
+{% endif %}
+ return
+ }
{% endif %}
}
@@ -378,10 +448,11 @@ table bridge vyos_filter {
{% for prior, conf in bridge.output.items() %}
chain VYOS_OUTPUT_{{ prior }} {
type filter hook output priority {{ prior }}; policy accept;
-{% if global_options.apply_to_bridged_traffic is vyos_defined %}
-{% if 'invalid_connections' in global_options.apply_to_bridged_traffic %}
- ct state invalid udp sport 67 udp dport 68 counter accept
- ct state invalid ether type arp counter accept
+{% if global_options.apply_to_bridged_traffic.accept_invalid is vyos_defined %}
+{% if 'ethernet_type' in global_options.apply_to_bridged_traffic.accept_invalid %}
+{% for ether_type in global_options.apply_to_bridged_traffic.accept_invalid.ethernet_type %}
+ {{ ether_type | nft_accept_invalid() }}
+{% endfor %}
{% endif %}
{% endif %}
{% if global_options.state_policy is vyos_defined %}
@@ -434,15 +505,15 @@ table bridge vyos_filter {
{% if global_options.state_policy is vyos_defined %}
chain VYOS_STATE_POLICY {
{% if global_options.state_policy.established is vyos_defined %}
- {{ global_options.state_policy.established | nft_state_policy('established') }}
+ {{ global_options.state_policy.established | nft_state_policy('established', bridge=True) }}
{% endif %}
{% if global_options.state_policy.invalid is vyos_defined %}
- {{ global_options.state_policy.invalid | nft_state_policy('invalid') }}
+ {{ global_options.state_policy.invalid | nft_state_policy('invalid', bridge=True) }}
{% endif %}
{% if global_options.state_policy.related is vyos_defined %}
- {{ global_options.state_policy.related | nft_state_policy('related') }}
+ {{ global_options.state_policy.related | nft_state_policy('related', bridge=True) }}
{% endif %}
return
}
{% endif %}
-} \ No newline at end of file
+}
diff --git a/data/templates/firewall/sysctl-firewall.conf.j2 b/data/templates/firewall/sysctl-firewall.conf.j2
index 6c33ffdc8..52806d066 100644
--- a/data/templates/firewall/sysctl-firewall.conf.j2
+++ b/data/templates/firewall/sysctl-firewall.conf.j2
@@ -1,6 +1,6 @@
# Autogenerated by firewall.py
-# gloabl options
+# global options
net.ipv4.icmp_echo_ignore_all = {{ 0 if global_options.all_ping == 'enable' else 1 }}
net.ipv4.icmp_echo_ignore_broadcasts = {{ 0 if global_options.broadcast_ping == 'enable' else 1 }}
net.ipv4.conf.all.bc_forwarding = {{ 1 if global_options.directed_broadcast == 'enable' else 0 }}
diff --git a/data/templates/frr/babeld.frr.j2 b/data/templates/frr/babeld.frr.j2
index 344a5f988..292bd9972 100644
--- a/data/templates/frr/babeld.frr.j2
+++ b/data/templates/frr/babeld.frr.j2
@@ -45,7 +45,6 @@ exit
{% endfor %}
{% endif %}
!
-{# Babel configuration #}
router babel
{% if parameters.diversity is vyos_defined %}
babel diversity
@@ -82,4 +81,3 @@ router babel
{% endif %}
exit
!
-end
diff --git a/data/templates/frr/bgpd.frr.j2 b/data/templates/frr/bgpd.frr.j2
index e5bfad59d..27d13c40c 100644
--- a/data/templates/frr/bgpd.frr.j2
+++ b/data/templates/frr/bgpd.frr.j2
@@ -1,13 +1,19 @@
{### MACRO definition for recurring peer patter, this can be either fed by a ###}
{### peer-group or an individual BGP neighbor ###}
{% macro bgp_neighbor(neighbor, config, peer_group=false) %}
+{# BGP order of peer-group and remote-as placement must be honored #}
{% if peer_group == true %}
neighbor {{ neighbor }} peer-group
-{% elif config.peer_group is vyos_defined %}
- neighbor {{ neighbor }} peer-group {{ config.peer_group }}
-{% endif %}
-{% if config.remote_as is vyos_defined %}
+{% if config.remote_as is vyos_defined %}
+ neighbor {{ neighbor }} remote-as {{ config.remote_as }}
+{% endif %}
+{% else %}
+{% if config.remote_as is vyos_defined %}
neighbor {{ neighbor }} remote-as {{ config.remote_as }}
+{% endif %}
+{% if config.peer_group is vyos_defined %}
+ neighbor {{ neighbor }} peer-group {{ config.peer_group }}
+{% endif %}
{% endif %}
{% if config.local_role is vyos_defined %}
{% for role, strict in config.local_role.items() %}
@@ -28,6 +34,9 @@
{% if config.bfd.profile is vyos_defined %}
neighbor {{ neighbor }} bfd profile {{ config.bfd.profile }}
{% endif %}
+{% if config.bfd.strict is vyos_defined %}
+ neighbor {{ neighbor }} bfd strict {{ 'hold-time ' ~ config.bfd.strict.hold_time if config.bfd.strict.hold_time is vyos_defined else '' }}
+{% endif %}
{% endif %}
{% if config.capability.dynamic is vyos_defined %}
neighbor {{ neighbor }} capability dynamic
@@ -92,6 +101,8 @@
{% endif %}
{% if config.enforce_first_as is vyos_defined %}
neighbor {{ neighbor }} enforce-first-as
+{% else %}
+ no neighbor {{ neighbor }} enforce-first-as
{% endif %}
{% if config.strict_capability_match is vyos_defined %}
neighbor {{ neighbor }} strict-capability-match
@@ -149,6 +160,8 @@
address-family ipv6 flowspec
{% elif afi == 'l2vpn_evpn' %}
address-family l2vpn evpn
+{% elif afi == 'link_state' %}
+ address-family link-state
{% endif %}
{% if afi_config.addpath_tx_all is vyos_defined %}
neighbor {{ neighbor }} addpath-tx-all-paths
@@ -245,11 +258,13 @@
neighbor {{ neighbor }} activate
exit-address-family
!
+{# j2lint: disable=jinja-statements-delimeter #}
{% endfor %}
{% endif %}
-{% endmacro %}
+{# j2lint: disable=jinja-statements-delimeter #}
+{%- endmacro -%}
!
-router bgp {{ system_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
+router bgp {{ system_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }} {{ 'as-notation ' ~ parameters.as_notation | replace('as', '') if parameters.as_notation is vyos_defined }}
{% if parameters.ebgp_requires_policy is vyos_defined %}
bgp ebgp-requires-policy
{% else %}
@@ -302,7 +317,9 @@ router bgp {{ system_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
{% if afi_config.redistribute is vyos_defined %}
{% for protocol, protocol_config in afi_config.redistribute.items() %}
{% if protocol == 'table' %}
- redistribute table {{ protocol_config.table }}
+{% for table, table_config in protocol_config.items() %}
+ redistribute table-direct {{ table }} {{ 'metric ' ~ table_config.metric if table_config.metric is vyos_defined }} {{ 'route-map ' ~ table_config.route_map if table_config.route_map is vyos_defined }}
+{% endfor %}
{% else %}
{% set redistribution_protocol = protocol %}
{% if protocol == 'ospfv3' %}
@@ -347,6 +364,9 @@ router bgp {{ system_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
import vrf {{ vrf }}
{% endfor %}
{% endif %}
+{% if afi_config.route_map.vrf.import is vyos_defined %}
+ import vrf route-map {{ afi_config.route_map.vrf.import }}
+{% endif %}
{% if afi_config.label.vpn.export is vyos_defined %}
label vpn export {{ afi_config.label.vpn.export }}
{% endif %}
@@ -495,12 +515,18 @@ router bgp {{ system_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
{% if bmp_config.monitor.ipv4_unicast.post_policy is vyos_defined %}
bmp monitor ipv4 unicast post-policy
{% endif %}
+{% if bmp_config.monitor.ipv4_unicast.local_rib is vyos_defined %}
+ bmp monitor ipv4 unicast loc-rib
+{% endif %}
{% if bmp_config.monitor.ipv6_unicast.pre_policy is vyos_defined %}
bmp monitor ipv6 unicast pre-policy
{% endif %}
{% if bmp_config.monitor.ipv6_unicast.post_policy is vyos_defined %}
bmp monitor ipv6 unicast post-policy
{% endif %}
+{% if bmp_config.monitor.ipv6_unicast.local_rib is vyos_defined %}
+ bmp monitor ipv6 unicast loc-rib
+{% endif %}
{% endif %}
{% if bmp_config.address is vyos_defined %}
bmp connect {{ bmp_config.address }} port {{ bmp_config.port }} min-retry {{ bmp_config.min_retry }} max-retry {{ bmp_config.max_retry }}
@@ -512,13 +538,15 @@ router bgp {{ system_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
{% if peer_group is vyos_defined %}
{% for peer, config in peer_group.items() %}
{{ bgp_neighbor(peer, config, true) }}
-{% endfor %}
+{# j2lint: disable=jinja-statements-delimeter #}
+{%- endfor %}
{% endif %}
!
{% if neighbor is vyos_defined %}
{% for peer, config in neighbor.items() %}
{{ bgp_neighbor(peer, config) }}
-{% endfor %}
+{# j2lint: disable=jinja-statements-delimeter #}
+{%- endfor %}
{% endif %}
!
{% if listen.limit is vyos_defined %}
@@ -621,11 +649,16 @@ bgp route-reflector allow-outbound-policy
{% if parameters.no_fast_external_failover is vyos_defined %}
no bgp fast-external-failover
{% endif %}
+{% if parameters.no_ipv6_auto_ra is vyos_defined %}
+ no bgp ipv6-auto-ra
+{% endif %}
{% if parameters.no_suppress_duplicates is vyos_defined %}
no bgp suppress-duplicates
{% endif %}
{% if parameters.reject_as_sets is vyos_defined %}
bgp reject-as-sets
+{% else %}
+ no bgp reject-as-sets
{% endif %}
{% if parameters.router_id is vyos_defined and parameters.router_id is not none %}
bgp router-id {{ parameters.router_id }}
@@ -639,6 +672,9 @@ bgp route-reflector allow-outbound-policy
{% if parameters.tcp_keepalive.idle is vyos_defined and parameters.tcp_keepalive.interval is vyos_defined and parameters.tcp_keepalive.probes is vyos_defined %}
bgp tcp-keepalive {{ parameters.tcp_keepalive.idle }} {{ parameters.tcp_keepalive.interval }} {{ parameters.tcp_keepalive.probes }}
{% endif %}
+{% if parameters.update_delay.max_delay is vyos_defined %}
+ update-delay {{ parameters.update_delay.max_delay }}{{ ' ' ~ parameters.update_delay.establish_wait if parameters.update_delay.establish_wait is vyos_defined }}
+{% endif %}
{% if srv6.locator is vyos_defined %}
segment-routing srv6
locator {{ srv6.locator }}
diff --git a/data/templates/frr/daemons.frr.tmpl b/data/templates/frr/daemons.frr.tmpl
index 3506528d2..b1159217f 100644
--- a/data/templates/frr/daemons.frr.tmpl
+++ b/data/templates/frr/daemons.frr.tmpl
@@ -4,7 +4,6 @@
# Note: The following FRR-services must be kept disabled because they are replaced by other packages in VyOS:
#
# pimd Replaced by package igmpproxy.
-# nhrpd Replaced by package opennhrp.
# pbrd Replaced by PBR in nftables.
# vrrpd Replaced by package keepalived.
#
@@ -13,7 +12,7 @@
# eigrp
# sharpd
# fabricd
-# pathd
+#
#
# The zebra, mgmtd and staticd daemons are always started and can not be disabled
#
@@ -30,7 +29,7 @@ isisd=yes
pimd=no
pim6d=yes
ldpd=yes
-nhrpd=no
+nhrpd=yes
eigrpd=no
babeld=yes
sharpd=no
@@ -38,7 +37,7 @@ pbrd=no
bfdd=yes
fabricd=yes
vrrpd=no
-pathd=no
+pathd=yes
#
# Define defaults for all services even those who shall be kept disabled.
@@ -104,9 +103,9 @@ vtysh_enable=yes
watchfrr_enable=yes
valgrind_enable=no
-#watchfrr_options=""
+watchfrr_options="--timeout={{ watchfrr_timeout }}"
-frr_profile="traditional"
+frr_profile="{{ profile }}"
MAX_FDS={{ descriptors }}
diff --git a/data/templates/frr/distribute_list_macro.j2 b/data/templates/frr/distribute_list_macro.j2
index c10bf732d..3e15ef100 100644
--- a/data/templates/frr/distribute_list_macro.j2
+++ b/data/templates/frr/distribute_list_macro.j2
@@ -27,4 +27,5 @@
{% if distribute_list.prefix_list.out is vyos_defined %}
distribute-list prefix {{ distribute_list.prefix_list.out }} out
{% endif %}
-{% endmacro %}
+{# j2lint: disable=jinja-statements-delimeter #}
+{%- endmacro -%}
diff --git a/data/templates/frr/evpn.mh.frr.j2 b/data/templates/frr/evpn.mh.frr.j2
index 03aaac44b..2fd7b7c09 100644
--- a/data/templates/frr/evpn.mh.frr.j2
+++ b/data/templates/frr/evpn.mh.frr.j2
@@ -1,16 +1,20 @@
!
-interface {{ ifname }}
-{% if evpn.es_df_pref is vyos_defined %}
- evpn mh es-df-pref {{ evpn.es_df_pref }}
-{% endif %}
-{% if evpn.es_id is vyos_defined %}
- evpn mh es-id {{ evpn.es_id }}
-{% endif %}
-{% if evpn.es_sys_mac is vyos_defined %}
- evpn mh es-sys-mac {{ evpn.es_sys_mac }}
-{% endif %}
-{% if evpn.uplink is vyos_defined %}
+{% if interfaces is vyos_defined %}
+{% for if_name, if_config in interfaces.items() %}
+interface {{ if_name }}
+{% if if_config.evpn.es_df_pref is vyos_defined %}
+ evpn mh es-df-pref {{ if_config.evpn.es_df_pref }}
+{% endif %}
+{% if if_config.evpn.es_id is vyos_defined %}
+ evpn mh es-id {{ if_config.evpn.es_id }}
+{% endif %}
+{% if if_config.evpn.es_sys_mac is vyos_defined %}
+ evpn mh es-sys-mac {{ if_config.evpn.es_sys_mac }}
+{% endif %}
+{% if if_config.evpn.uplink is vyos_defined %}
evpn mh uplink
-{% endif %}
+{% endif %}
exit
!
+{% endfor %}
+{% endif %}
diff --git a/data/templates/frr/fabricd.frr.j2 b/data/templates/frr/fabricd.frr.j2
index 8f2ae6466..27110f6ae 100644
--- a/data/templates/frr/fabricd.frr.j2
+++ b/data/templates/frr/fabricd.frr.j2
@@ -39,7 +39,7 @@ exit
router openfabric {{ name }}
net {{ net }}
{% if router_config.domain_password.md5 is vyos_defined %}
- domain-password md5 {{ router_config.domain_password.plaintext_password }}
+ domain-password md5 {{ router_config.domain_password.md5 }}
{% elif router_config.domain_password.plaintext_password is vyos_defined %}
domain-password clear {{ router_config.domain_password.plaintext_password }}
{% endif %}
@@ -70,3 +70,4 @@ router openfabric {{ name }}
exit
!
{% endfor %}
+!
diff --git a/data/templates/frr/ipv6_distribute_list_macro.j2 b/data/templates/frr/ipv6_distribute_list_macro.j2
index c365fbdae..2f483b7d4 100644
--- a/data/templates/frr/ipv6_distribute_list_macro.j2
+++ b/data/templates/frr/ipv6_distribute_list_macro.j2
@@ -27,4 +27,5 @@
{% if distribute_list.prefix_list.out is vyos_defined %}
ipv6 distribute-list prefix {{ distribute_list.prefix_list.out }} out
{% endif %}
-{% endmacro %}
+{# j2lint: disable=jinja-statements-delimeter #}
+{%- endmacro -%}
diff --git a/data/templates/frr/isisd.frr.j2 b/data/templates/frr/isisd.frr.j2
index eb14aade6..75b98c091 100644
--- a/data/templates/frr/isisd.frr.j2
+++ b/data/templates/frr/isisd.frr.j2
@@ -16,6 +16,33 @@ interface {{ iface }}
{% if iface_config.circuit_type is vyos_defined %}
isis circuit-type {{ iface_config.circuit_type }}
{% endif %}
+{% if iface_config.fast_reroute.lfa is vyos_defined %}
+{% for level, level_config in iface_config.fast_reroute.lfa.items() %}
+{% if level_config.enable is vyos_defined %}
+isis fast-reroute lfa {{ level | replace('_', '-') }}
+{% endif %}
+{% if level_config.exclude.interface is vyos_defined %}
+{% for excl_if in level_config.exclude.interface %}
+isis fast-reroute lfa {{ level | replace('_', '-') }} exclude interface {{ excl_if }}
+{% endfor %}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if iface_config.fast_reroute.remote_lfa is vyos_defined %}
+{% for level, level_config in iface_config.fast_reroute.remote_lfa.items() %}
+{% if level_config.maximum_metric is vyos_defined %}
+isis fast-reroute remote-lfa maximum-metric {{ level_config.maximum_metric }} {{ level | replace('_', '-') }}
+{% endif %}
+{% if level_config.tunnel.mpls_ldp is vyos_defined %}
+isis fast-reroute remote-lfa tunnel mpls-ldp {{ level | replace('_', '-') }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if iface_config.fast_reroute.ti_lfa is vyos_defined %}
+{% for level, level_config in iface_config.fast_reroute.ti_lfa.items() %}
+isis fast-reroute ti-lfa {{ level | replace('_', '-') }} {{ 'node-protection' if level_config.node_protection is vyos_defined }} {{ 'link-fallback' if level_config.node_protection.link_fallback is vyos_defined }}
+{% endfor %}
+{% endif %}
{% if iface_config.hello_interval is vyos_defined %}
isis hello-interval {{ iface_config.hello_interval }}
{% endif %}
@@ -80,25 +107,17 @@ advertise-passive-only
metric-style {{ metric_style }}
{% endif %}
{% if domain_password.md5 is vyos_defined %}
- domain-password md5 {{ domain_password.plaintext_password }}
+ domain-password md5 {{ domain_password.md5 }}
{% elif domain_password.plaintext_password is vyos_defined %}
domain-password clear {{ domain_password.plaintext_password }}
{% endif %}
{% if log_adjacency_changes is vyos_defined %}
log-adjacency-changes
{% endif %}
-{% if lsp_gen_interval is vyos_defined %}
- lsp-gen-interval {{ lsp_gen_interval }}
-{% endif %}
+ lsp-timers gen-interval {{ lsp_gen_interval }} refresh-interval {{ lsp_refresh_interval }} max-lifetime {{ max_lsp_lifetime }}
{% if lsp_mtu is vyos_defined %}
lsp-mtu {{ lsp_mtu }}
{% endif %}
-{% if lsp_refresh_interval is vyos_defined %}
- lsp-refresh-interval {{ lsp_refresh_interval }}
-{% endif %}
-{% if max_lsp_lifetime is vyos_defined %}
- max-lsp-lifetime {{ max_lsp_lifetime }}
-{% endif %}
{% if ldp_sync.holddown is vyos_defined %}
mpls ldp-sync holddown {{ ldp_sync.holddown }}
{% elif ldp_sync is vyos_defined %}
@@ -126,10 +145,39 @@ advertise-passive-only
{% endif %}
mpls-te inter-as{{ level }}
{% endif %}
+{% if traffic_engineering.export is vyos_defined %}
+ mpls-te export
+{% endif %}
{% if segment_routing is vyos_defined %}
{% if segment_routing.maximum_label_depth is vyos_defined %}
segment-routing node-msd {{ segment_routing.maximum_label_depth }}
{% endif %}
+{% if segment_routing.srv6 is vyos_defined %}
+ segment-routing srv6
+{% if segment_routing.srv6.locator is vyos_defined %}
+ locator {{ segment_routing.srv6.locator }}
+{% endif %}
+{% if segment_routing.srv6.node_msd is vyos_defined %}
+ node-msd
+{% if segment_routing.srv6.node_msd.max_end_d is vyos_defined %}
+ max-end-d {{ segment_routing.srv6.node_msd.max_end_d }}
+{% endif %}
+{% if segment_routing.srv6.node_msd.max_end_pop is vyos_defined %}
+ max-end-pop {{ segment_routing.srv6.node_msd.max_end_pop }}
+{% endif %}
+{% if segment_routing.srv6.node_msd.max_h_encaps is vyos_defined %}
+ max-h-encaps {{ segment_routing.srv6.node_msd.max_h_encaps }}
+{% endif %}
+{% if segment_routing.srv6.node_msd.max_segs_left is vyos_defined %}
+ max-segs-left {{ segment_routing.srv6.node_msd.max_segs_left }}
+{% endif %}
+ exit
+{% endif %}
+{% if segment_routing.srv6.interface is vyos_defined %}
+ interface {{ segment_routing.srv6.interface }}
+{% endif %}
+ exit
+{% endif %}
{% if segment_routing.global_block is vyos_defined %}
{% if segment_routing.local_block is vyos_defined %}
segment-routing global-block {{ segment_routing.global_block.low_label_value }} {{ segment_routing.global_block.high_label_value }} local-block {{ segment_routing.local_block.low_label_value }} {{ segment_routing.local_block.high_label_value }}
diff --git a/data/templates/frr/ldpd.frr.j2 b/data/templates/frr/ldpd.frr.j2
index 9a893cc55..b8fb0cfc7 100644
--- a/data/templates/frr/ldpd.frr.j2
+++ b/data/templates/frr/ldpd.frr.j2
@@ -82,8 +82,11 @@ mpls ldp
{% endfor %}
{% endif %}
{% if ldp.interface is vyos_defined %}
-{% for interface in ldp.interface %}
+{% for interface, iface_config in ldp.interface.items() %}
interface {{ interface }}
+{% if iface_config.disable_establish_hello is vyos_defined %}
+ disable-establish-hello
+{% endif %}
exit
{% endfor %}
{% endif %}
@@ -135,8 +138,11 @@ mpls ldp
{% endfor %}
{% endif %}
{% if ldp.interface is vyos_defined %}
-{% for interface in ldp.interface %}
+{% for interface, iface_config in ldp.interface.items() %}
interface {{ interface }}
+{% if iface_config.disable_establish_hello is vyos_defined %}
+ disable-establish-hello
+{% endif %}
{% endfor %}
{% endif %}
exit-address-family
diff --git a/data/templates/frr/nhrpd.frr.j2 b/data/templates/frr/nhrpd.frr.j2
new file mode 100644
index 000000000..813a9384b
--- /dev/null
+++ b/data/templates/frr/nhrpd.frr.j2
@@ -0,0 +1,60 @@
+!
+{% if redirect is vyos_defined %}
+nhrp nflog-group {{ redirect }}
+{% endif %}
+{% if multicast is vyos_defined %}
+nhrp multicast-nflog-group {{ multicast }}
+{% endif %}
+{% if tunnel is vyos_defined %}
+{% for iface, iface_config in tunnel.items() %}
+interface {{ iface }}
+{% if iface_config.authentication is vyos_defined %}
+ ip nhrp authentication {{ iface_config.authentication }}
+{% endif %}
+{% if iface_config.holdtime is vyos_defined %}
+ ip nhrp holdtime {{ iface_config.holdtime }}
+{% endif %}
+{% if iface_config.map.tunnel_ip is vyos_defined %}
+{% for tunip, tunip_config in iface_config.map.tunnel_ip.items() %}
+{% if tunip_config.nbma is vyos_defined %}
+ ip nhrp map {{ tunip }} {{ tunip_config.nbma }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if iface_config.mtu is vyos_defined %}
+ ip nhrp mtu {{ iface_config.mtu }}
+{% endif %}
+{% if iface_config.multicast is vyos_defined %}
+{% for multicast_ip in iface_config.multicast %}
+ ip nhrp map multicast {{ multicast_ip }}
+{% endfor %}
+{% endif %}
+{% if iface_config.nhs.tunnel_ip is vyos_defined %}
+{% for tunip, tunip_config in iface_config.nhs.tunnel_ip.items() %}
+{% if tunip_config.nbma is vyos_defined %}
+{% for nbmaip in tunip_config.nbma %}
+ ip nhrp nhs {{ tunip }} nbma {{ nbmaip }}
+{% endfor %}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if iface_config.network_id is vyos_defined %}
+ ip nhrp network-id {{ iface_config.network_id }}
+{% endif %}
+{% if iface_config.redirect is vyos_defined %}
+ ip nhrp redirect
+{% endif %}
+{% if iface_config.registration_no_unique is vyos_defined %}
+ ip nhrp registration no-unique
+{% endif %}
+{% if iface_config.shortcut is vyos_defined %}
+ ip nhrp shortcut
+{% endif %}
+{% if iface_config.security_profile is vyos_defined %}
+ tunnel protection vici profile dmvpn-{{ iface_config.security_profile }}-{{ iface }}-child
+{% endif %}
+exit
+!
+{% endfor %}
+{% endif %}
+!
diff --git a/data/templates/frr/nhrpd_nftables.conf.j2 b/data/templates/frr/nhrpd_nftables.conf.j2
new file mode 100644
index 000000000..6ae35ef52
--- /dev/null
+++ b/data/templates/frr/nhrpd_nftables.conf.j2
@@ -0,0 +1,46 @@
+#!/usr/sbin/nft -f
+
+table ip vyos_nhrp_multicast
+table ip vyos_nhrp_redirect
+delete table ip vyos_nhrp_multicast
+delete table ip vyos_nhrp_redirect
+{% if multicast is vyos_defined %}
+table ip vyos_nhrp_multicast {
+ chain VYOS_NHRP_MULTICAST_OUTPUT {
+ type filter hook output priority filter+10; policy accept;
+{% if tunnel is vyos_defined %}
+{% for tun, tunnel_conf in tunnel.items() %}
+{% if tunnel_conf.multicast is vyos_defined %}
+ oifname "{{ tun }}" ip daddr 224.0.0.0/24 counter log group {{ multicast }}
+ oifname "{{ tun }}" ip daddr 224.0.0.0/24 counter drop
+{% endif %}
+{% endfor %}
+{% endif %}
+ }
+ chain VYOS_NHRP_MULTICAST_FORWARD {
+ type filter hook forward priority filter+10; policy accept;
+{% if tunnel is vyos_defined %}
+{% for tun, tunnel_conf in tunnel.items() %}
+{% if tunnel_conf.multicast is vyos_defined %}
+ oifname "{{ tun }}" ip daddr 224.0.0.0/4 counter log group {{ multicast }}
+ oifname "{{ tun }}" ip daddr 224.0.0.0/4 counter drop
+{% endif %}
+{% endfor %}
+{% endif %}
+ }
+}
+{% endif %}
+{% if redirect is vyos_defined %}
+table ip vyos_nhrp_redirect {
+ chain VYOS_NHRP_REDIRECT_FORWARD {
+ type filter hook forward priority filter+10; policy accept;
+{% if tunnel is vyos_defined %}
+{% for tun, tunnel_conf in tunnel.items() %}
+{% if tunnel_conf.redirect is vyos_defined %}
+ iifname "{{ tun }}" oifname "{{ tun }}" meter loglimit-0 size 65535 { ip daddr & 255.255.255.0 . ip saddr & 255.255.255.0 timeout 1m limit rate 4/minute burst 1 packets } counter log group {{ redirect }}
+{% endif %}
+{% endfor %}
+{% endif %}
+ }
+}
+{% endif %}
diff --git a/data/templates/frr/ospfd.frr.j2 b/data/templates/frr/ospfd.frr.j2
index ab074b6a2..a3a8c5bcb 100644
--- a/data/templates/frr/ospfd.frr.j2
+++ b/data/templates/frr/ospfd.frr.j2
@@ -3,6 +3,7 @@
{% for iface, iface_config in interface.items() %}
interface {{ iface }}
{% if iface_config.authentication.plaintext_password is vyos_defined %}
+ ip ospf authentication
ip ospf authentication-key {{ iface_config.authentication.plaintext_password }}
{% elif iface_config.authentication.md5 is vyos_defined %}
ip ospf authentication message-digest
@@ -11,6 +12,8 @@ interface {{ iface }}
ip ospf message-digest-key {{ key }} md5 {{ key_config.md5_key }}
{% endfor %}
{% endif %}
+{% elif iface_config.authentication.null is vyos_defined %}
+ ip ospf authentication null
{% endif %}
{% if iface_config.area is vyos_defined %}
ip ospf area {{ iface_config.area }}
@@ -30,6 +33,9 @@ interface {{ iface }}
{% if iface_config.retransmit_interval is vyos_defined %}
ip ospf retransmit-interval {{ iface_config.retransmit_interval }}
{% endif %}
+{% if iface_config.retransmit_window is vyos_defined %}
+ ip ospf retransmit-window {{ iface_config.retransmit_window }}
+{% endif %}
{% if iface_config.transmit_delay is vyos_defined %}
ip ospf transmit-delay {{ iface_config.transmit_delay }}
{% endif %}
@@ -79,7 +85,7 @@ router ospf {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
{% for area_id, area_config in area.items() %}
{% if area_config.area_type is vyos_defined %}
{% for type, type_config in area_config.area_type.items() if type != 'normal' %}
- area {{ area_id }} {{ type }} {{ 'no-summary' if type_config.no_summary is vyos_defined }}
+ area {{ area_id }} {{ type }} {{ 'translate-' + type_config.translate if type_config.translate is vyos_defined }} {{ 'no-summary' if type_config.no_summary is vyos_defined }}
{% if type_config.default_cost is vyos_defined %}
area {{ area_id }} default-cost {{ type_config.default_cost }}
{% endif %}
@@ -118,14 +124,17 @@ router ospf {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
{% if area_config.virtual_link is vyos_defined %}
{% for link, link_config in area_config.virtual_link.items() %}
{% if link_config.authentication.plaintext_password is vyos_defined %}
+ area {{ area_id }} virtual-link {{ link }} authentication
area {{ area_id }} virtual-link {{ link }} authentication-key {{ link_config.authentication.plaintext_password }}
{% elif link_config.authentication.md5.key_id is vyos_defined %}
{% for key, key_config in link_config.authentication.md5.key_id.items() %}
area {{ area_id }} virtual-link {{ link }} message-digest-key {{ key }} md5 {{ key_config.md5_key }}
{% endfor %}
+{% elif link_config.authentication.null is vyos_defined %}
+ area {{ area_id }} virtual-link {{ link }} authentication null
{% endif %}
{# The following values are default values #}
- area {{ area_id }} virtual-link {{ link }} hello-interval {{ link_config.hello_interval }} retransmit-interval {{ link_config.retransmit_interval }} transmit-delay {{ link_config.transmit_delay }} dead-interval {{ link_config.dead_interval }}
+ area {{ area_id }} virtual-link {{ link }} hello-interval {{ link_config.hello_interval }} retransmit-interval {{ link_config.retransmit_interval }} retransmit-window {{ link_config.retransmit_window }} transmit-delay {{ link_config.transmit_delay }} dead-interval {{ link_config.dead_interval }}
{% endfor %}
{% endif %}
{% endfor %}
@@ -217,7 +226,7 @@ router ospf {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
{% for protocol, options in redistribute.items() %}
{% if protocol == 'table' %}
{% for table, table_options in options.items() %}
- redistribute {{ protocol }} {{ table }} {{ 'metric ' ~ table_options.metric if table_options.metric is vyos_defined }} {{ 'metric-type ' ~ table_options.metric_type if table_options.metric_type is vyos_defined }} {{ 'route-map ' ~ table_options.route_map if table_options.route_map is vyos_defined }}
+ redistribute table-direct {{ table }} {{ 'metric ' ~ table_options.metric if table_options.metric is vyos_defined }} {{ 'metric-type ' ~ table_options.metric_type if table_options.metric_type is vyos_defined }} {{ 'route-map ' ~ table_options.route_map if table_options.route_map is vyos_defined }}
{% endfor %}
{% else %}
redistribute {{ protocol }} {{ 'metric ' ~ options.metric if options.metric is vyos_defined }} {{ 'metric-type ' ~ options.metric_type if options.metric_type is vyos_defined }} {{ 'route-map ' ~ options.route_map if options.route_map is vyos_defined }}
@@ -233,6 +242,7 @@ router ospf {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
{% endfor %}
{% endif %}
{% if segment_routing is vyos_defined %}
+ segment-routing on
{% if segment_routing.maximum_label_depth is vyos_defined %}
segment-routing node-msd {{ segment_routing.maximum_label_depth }}
{% endif %}
@@ -252,7 +262,6 @@ router ospf {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
{% endif %}
{% endfor %}
{% endif %}
- segment-routing on
{% endif %}
{% if timers.throttle.spf.delay is vyos_defined and timers.throttle.spf.initial_holdtime is vyos_defined and timers.throttle.spf.max_holdtime is vyos_defined %}
{# Timer values have default values #}
diff --git a/data/templates/frr/pim6d.frr.j2 b/data/templates/frr/pim6d.frr.j2
index bac716fcc..d4144a2f9 100644
--- a/data/templates/frr/pim6d.frr.j2
+++ b/data/templates/frr/pim6d.frr.j2
@@ -40,10 +40,10 @@ interface {{ iface }}
{% for group, group_config in iface_config.mld.join.items() %}
{% if group_config.source is vyos_defined %}
{% for source in group_config.source %}
- ipv6 mld join {{ group }} {{ source }}
+ ipv6 mld join-group {{ group }} {{ source }}
{% endfor %}
{% else %}
- ipv6 mld join {{ group }}
+ ipv6 mld join-group {{ group }}
{% endif %}
{% endfor %}
{% endif %}
@@ -52,30 +52,33 @@ exit
{% endfor %}
{% endif %}
!
+router pim6
{% if join_prune_interval is vyos_defined %}
-ipv6 pim join-prune-interval {{ join_prune_interval }}
+ join-prune-interval {{ join_prune_interval }}
{% endif %}
{% if keep_alive_timer is vyos_defined %}
-ipv6 pim keep-alive-timer {{ keep_alive_timer }}
+ keep-alive-timer {{ keep_alive_timer }}
{% endif %}
{% if packets is vyos_defined %}
-ipv6 pim packets {{ packets }}
+ packets {{ packets }}
{% endif %}
{% if register_suppress_time is vyos_defined %}
-ipv6 pim register-suppress-time {{ register_suppress_time }}
+ register-suppress-time {{ register_suppress_time }}
{% endif %}
{% if rp.address is vyos_defined %}
{% for address, address_config in rp.address.items() %}
{% if address_config.group is vyos_defined %}
{% for group in address_config.group %}
-ipv6 pim rp {{ address }} {{ group }}
+ rp {{ address }} {{ group }}
{% endfor %}
{% endif %}
{% if address_config.prefix_list6 is vyos_defined %}
-ipv6 pim rp {{ address }} prefix-list {{ address_config.prefix_list6 }}
+ rp {{ address }} prefix-list {{ address_config.prefix_list6 }}
{% endif %}
{% endfor %}
{% endif %}
{% if rp.keep_alive_timer is vyos_defined %}
-ipv6 pim rp keep-alive-timer {{ rp.keep_alive_timer }}
+ rp keep-alive-timer {{ rp.keep_alive_timer }}
{% endif %}
+exit
+!
diff --git a/data/templates/frr/pimd.frr.j2 b/data/templates/frr/pimd.frr.j2
index 68edf4a5c..d474d8495 100644
--- a/data/templates/frr/pimd.frr.j2
+++ b/data/templates/frr/pimd.frr.j2
@@ -39,10 +39,10 @@ interface {{ iface }}
{% for join, join_config in iface_config.igmp.join.items() %}
{% if join_config.source_address is vyos_defined %}
{% for source_address in join_config.source_address %}
- ip igmp join {{ join }} {{ source_address }}
+ ip igmp join-group {{ join }} {{ source_address }}
{% endfor %}
{% else %}
- ip igmp join {{ join }}
+ ip igmp join-group {{ join }}
{% endif %}
{% endfor %}
{% endif %}
@@ -51,45 +51,47 @@ exit
{% endfor %}
{% endif %}
!
+{% if igmp.watermark_warning is vyos_defined %}
+ip igmp watermark-warn {{ igmp.watermark_warning }}
+{% endif %}
+!
+router pim
{% if ecmp is vyos_defined %}
-ip pim ecmp {{ 'rebalance' if ecmp.rebalance is vyos_defined }}
+ ecmp {{ 'rebalance' if ecmp.rebalance is vyos_defined }}
{% endif %}
{% if join_prune_interval is vyos_defined %}
-ip pim join-prune-interval {{ join_prune_interval }}
+ join-prune-interval {{ join_prune_interval }}
{% endif %}
{% if keep_alive_timer is vyos_defined %}
-ip pim keep-alive-timer {{ keep_alive_timer }}
+ keep-alive-timer {{ keep_alive_timer }}
{% endif %}
{% if packets is vyos_defined %}
-ip pim packets {{ packets }}
+ packets {{ packets }}
{% endif %}
{% if register_accept_list.prefix_list is vyos_defined %}
-ip pim register-accept-list {{ register_accept_list.prefix_list }}
+ register-accept-list {{ register_accept_list.prefix_list }}
{% endif %}
{% if register_suppress_time is vyos_defined %}
-ip pim register-suppress-time {{ register_suppress_time }}
+ register-suppress-time {{ register_suppress_time }}
{% endif %}
{% if rp.address is vyos_defined %}
{% for address, address_config in rp.address.items() %}
{% for group in address_config.group %}
-ip pim rp {{ address }} {{ group }}
+ rp {{ address }} {{ group }}
{% endfor %}
{% endfor %}
{% endif %}
{% if rp.keep_alive_timer is vyos_defined %}
-ip pim rp keep-alive-timer {{ rp.keep_alive_timer }}
+ rp keep-alive-timer {{ rp.keep_alive_timer }}
{% endif %}
{% if no_v6_secondary is vyos_defined %}
-no ip pim send-v6-secondary
+ no send-v6-secondary
{% endif %}
{% if spt_switchover.infinity_and_beyond is vyos_defined %}
-ip pim spt-switchover infinity-and-beyond {{ 'prefix-list ' ~ spt_switchover.infinity_and_beyond.prefix_list if spt_switchover.infinity_and_beyond.prefix_list is defined }}
+ spt-switchover infinity-and-beyond {{ 'prefix-list ' ~ spt_switchover.infinity_and_beyond.prefix_list if spt_switchover.infinity_and_beyond.prefix_list is defined }}
{% endif %}
{% if ssm.prefix_list is vyos_defined %}
-ip pim ssm prefix-list {{ ssm.prefix_list }}
-{% endif %}
-!
-{% if igmp.watermark_warning is vyos_defined %}
-ip igmp watermark-warn {{ igmp.watermark_warning }}
+ ssm prefix-list {{ ssm.prefix_list }}
{% endif %}
+exit
!
diff --git a/data/templates/frr/policy.frr.j2 b/data/templates/frr/policy.frr.j2
index ed5876ae9..27add3f24 100644
--- a/data/templates/frr/policy.frr.j2
+++ b/data/templates/frr/policy.frr.j2
@@ -245,6 +245,9 @@ route-map {{ route_map }} {{ rule_config.action }} {{ rule }}
{% if rule_config.match.peer is vyos_defined %}
match peer {{ rule_config.match.peer }}
{% endif %}
+{% if rule_config.match.source_peer is vyos_defined %}
+ match src-peer {{ rule_config.match.source_peer }}
+{% endif %}
{% if rule_config.match.protocol is vyos_defined %}
{% set source_protocol = 'ospf6' if rule_config.match.protocol == 'ospfv3' else rule_config.match.protocol %}
match source-protocol {{ source_protocol }}
@@ -252,6 +255,12 @@ route-map {{ route_map }} {{ rule_config.action }} {{ rule }}
{% if rule_config.match.rpki is vyos_defined %}
match rpki {{ rule_config.match.rpki }}
{% endif %}
+{% if rule_config.match.rpki_extcommunity is vyos_defined %}
+ match rpki-extcommunity {{ rule_config.match.rpki_extcommunity }}
+{% endif %}
+{% if rule_config.match.source_vrf is vyos_defined %}
+ match source-vrf {{ rule_config.match.source_vrf }}
+{% endif %}
{% if rule_config.match.tag is vyos_defined %}
match tag {{ rule_config.match.tag }}
{% endif %}
diff --git a/data/templates/frr/rpki.frr.j2 b/data/templates/frr/rpki.frr.j2
index 59724102c..e35f99766 100644
--- a/data/templates/frr/rpki.frr.j2
+++ b/data/templates/frr/rpki.frr.j2
@@ -1,24 +1,34 @@
-!
+{% macro rpki_config(rpki) %}
{# as FRR does not support deleting the entire rpki section we leave it in place even when it's empty #}
rpki
-{% if cache is vyos_defined %}
-{% for peer, peer_config in cache.items() %}
+{% if rpki.cache is vyos_defined %}
+{% for peer, peer_config in rpki.cache.items() %}
{# port is mandatory and preference uses a default value #}
{% if peer_config.ssh.username is vyos_defined %}
- rpki cache {{ peer | replace('_', '-') }} {{ peer_config.port }} {{ peer_config.ssh.username }} {{ peer_config.ssh.private_key_file }} {{ peer_config.ssh.public_key_file }} preference {{ peer_config.preference }}
+ rpki cache ssh {{ peer | replace('_', '-') }} {{ peer_config.port }} {{ peer_config.ssh.username }} {{ peer_config.ssh.private_key_file }} {{ peer_config.ssh.public_key_file }}{{ ' source ' ~ peer_config.source_address if peer_config.source_address is vyos_defined }} preference {{ peer_config.preference }}
{% else %}
- rpki cache {{ peer | replace('_', '-') }} {{ peer_config.port }} preference {{ peer_config.preference }}
+ rpki cache tcp {{ peer | replace('_', '-') }} {{ peer_config.port }}{{ ' source ' ~ peer_config.source_address if peer_config.source_address is vyos_defined }} preference {{ peer_config.preference }}
{% endif %}
{% endfor %}
{% endif %}
-{% if expire_interval is vyos_defined %}
- rpki expire_interval {{ expire_interval }}
+{% if rpki.expire_interval is vyos_defined %}
+ rpki expire_interval {{ rpki.expire_interval }}
{% endif %}
-{% if polling_period is vyos_defined %}
- rpki polling_period {{ polling_period }}
+{% if rpki.polling_period is vyos_defined %}
+ rpki polling_period {{ rpki.polling_period }}
{% endif %}
-{% if retry_interval is vyos_defined %}
- rpki retry_interval {{ retry_interval }}
+{% if rpki.retry_interval is vyos_defined %}
+ rpki retry_interval {{ rpki.retry_interval }}
{% endif %}
exit
+{# j2lint: disable=jinja-statements-delimeter #}
+{%- endmacro -%}
+!
+{% if rpki.vrf is vyos_defined %}
+vrf {{ rpki.vrf }}
+ {{ rpki_config(rpki) | indent(width=1) }}
+exit-vrf
+{% else %}
+{{ rpki_config(rpki) }}
+{% endif %}
!
diff --git a/data/templates/frr/static_mcast.frr.j2 b/data/templates/frr/static_mcast.frr.j2
deleted file mode 100644
index 54b2790b0..000000000
--- a/data/templates/frr/static_mcast.frr.j2
+++ /dev/null
@@ -1,11 +0,0 @@
-!
-{% for route_gr in mroute %}
-{% for nh in mroute[route_gr] %}
-{% if mroute[route_gr][nh] %}
-ip mroute {{ route_gr }} {{ nh }} {{ mroute[route_gr][nh] }}
-{% else %}
-ip mroute {{ route_gr }} {{ nh }}
-{% endif %}
-{% endfor %}
-{% endfor %}
-!
diff --git a/data/templates/frr/static_routes_macro.j2 b/data/templates/frr/static_routes_macro.j2
deleted file mode 100644
index cf8046968..000000000
--- a/data/templates/frr/static_routes_macro.j2
+++ /dev/null
@@ -1,29 +0,0 @@
-{% macro static_routes(ip_ipv6, prefix, prefix_config, table=None) %}
-{% if prefix_config.blackhole is vyos_defined %}
-{{ ip_ipv6 }} route {{ prefix }} blackhole {{ prefix_config.blackhole.distance if prefix_config.blackhole.distance is vyos_defined }} {{ 'tag ' ~ prefix_config.blackhole.tag if prefix_config.blackhole.tag is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined and table is not none }}
-{% endif %}
-{% if prefix_config.reject is vyos_defined %}
-{{ ip_ipv6 }} route {{ prefix }} reject {{ prefix_config.reject.distance if prefix_config.reject.distance is vyos_defined }} {{ 'tag ' ~ prefix_config.reject.tag if prefix_config.reject.tag is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined }}
-{% endif %}
-{% if prefix_config.dhcp_interface is vyos_defined %}
-{% set next_hop = prefix_config.dhcp_interface | get_dhcp_router %}
-{% if next_hop is vyos_defined %}
-{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ prefix_config.dhcp_interface }} {{ 'table ' ~ table if table is vyos_defined }}
-{% endif %}
-{% endif %}
-{% if prefix_config.interface is vyos_defined %}
-{% for interface, interface_config in prefix_config.interface.items() if interface_config.disable is not defined %}
-{{ ip_ipv6 }} route {{ prefix }} {{ interface }} {{ interface_config.distance if interface_config.distance is vyos_defined }} {{ 'nexthop-vrf ' ~ interface_config.vrf if interface_config.vrf is vyos_defined }} {{ 'segments ' ~ interface_config.segments if interface_config.segments is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined }}
-{% endfor %}
-{% endif %}
-{% if prefix_config.next_hop is vyos_defined and prefix_config.next_hop is not none %}
-{% for next_hop, next_hop_config in prefix_config.next_hop.items() if next_hop_config.disable is not defined %}
-{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ next_hop_config.interface if next_hop_config.interface is vyos_defined }} {{ next_hop_config.distance if next_hop_config.distance is vyos_defined }} {{ 'nexthop-vrf ' ~ next_hop_config.vrf if next_hop_config.vrf is vyos_defined }} {{ 'bfd profile ' ~ next_hop_config.bfd.profile if next_hop_config.bfd.profile is vyos_defined }} {{ 'segments ' ~ next_hop_config.segments if next_hop_config.segments is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined }}
-{% if next_hop_config.bfd.multi_hop.source is vyos_defined %}
-{% for source, source_config in next_hop_config.bfd.multi_hop.source.items() %}
-{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} bfd multi-hop source {{ source }} profile {{ source_config.profile }}
-{% endfor %}
-{% endif %}
-{% endfor %}
-{% endif %}
-{% endmacro %}
diff --git a/data/templates/frr/staticd.frr.j2 b/data/templates/frr/staticd.frr.j2
index 992a0435c..18d300dae 100644
--- a/data/templates/frr/staticd.frr.j2
+++ b/data/templates/frr/staticd.frr.j2
@@ -1,19 +1,85 @@
-{% from 'frr/static_routes_macro.j2' import static_routes %}
+{# Common macro for recurroiing options for a static route #}
+{% macro route_options(route, interface_or_next_hop, config, table) %}
+{# j2lint: disable=jinja-statements-delimeter #}
+{% set ip_route = route ~ ' ' ~ interface_or_next_hop %}
+{% if config.interface is vyos_defined %}
+{% set ip_route = ip_route ~ ' ' ~ config.interface %}
+{% endif %}
+{% if config.tag is vyos_defined %}
+{% set ip_route = ip_route ~ ' tag ' ~ config.tag %}
+{% endif %}
+{% if config.distance is vyos_defined %}
+{% set ip_route = ip_route ~ ' ' ~ config.distance %}
+{% endif %}
+{% if config.bfd is vyos_defined %}
+{% set ip_route = ip_route ~ ' bfd' %}
+{% if config.bfd.multi_hop is vyos_defined %}
+{% set ip_route = ip_route ~ ' multi-hop' %}
+{% if config.bfd.multi_hop.source_address is vyos_defined %}
+{% set ip_route = ip_route ~ ' source ' ~ config.bfd.multi_hop.source_address %}
+{% endif %}
+{% endif %}
+{% if config.bfd.profile is vyos_defined %}
+{% set ip_route = ip_route ~ ' profile ' ~ config.bfd.profile %}
+{% endif %}
+{% endif %}
+{% if config.vrf is vyos_defined %}
+{% set ip_route = ip_route ~ ' nexthop-vrf ' ~ config.vrf %}
+{% endif %}
+{% if config.segments is vyos_defined %}
+{# Segments used in/for SRv6 #}
+{% set ip_route = ip_route ~ ' segments ' ~ config.segments %}
+{% endif %}
+{# Routing table to configure #}
+{% if table is vyos_defined %}
+{% set ip_route = ip_route ~ ' table ' ~ table %}
+{% endif %}
+{{ ip_route }}
+{%- endmacro -%}
+{# Build static IPv4/IPv6 route #}
+{% macro static_routes(ip_ipv6, prefix, prefix_config, table=None) %}
+{% set route = ip_ipv6 ~ 'route ' ~ prefix %}
+{% if prefix_config.interface is vyos_defined %}
+{% for interface, interface_config in prefix_config.interface.items() if interface_config.disable is not defined %}
+{{ route_options(route, interface, interface_config, table) }}
+{% endfor %}
+{% endif %}
+{% if prefix_config.next_hop is vyos_defined and prefix_config.next_hop is not none %}
+{% for next_hop, next_hop_config in prefix_config.next_hop.items() if next_hop_config.disable is not defined %}
+{{ route_options(route, next_hop, next_hop_config, table) }}
+{% endfor %}
+{% endif %}
+{% if prefix_config.dhcp_interface is vyos_defined %}
+{% for dhcp_interface in prefix_config.dhcp_interface %}
+{% set next_hop = dhcp_interface | get_dhcp_router %}
+{% if next_hop is vyos_defined %}
+{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ dhcp_interface }} {{ 'table ' ~ table if table is vyos_defined }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if prefix_config.blackhole is vyos_defined %}
+{{ route_options(route, 'blackhole', prefix_config.blackhole, table) }}
+{% elif prefix_config.reject is vyos_defined %}
+{{ route_options(route, 'reject', prefix_config.reject, table) }}
+{% endif %}
+{# j2lint: disable=jinja-statements-delimeter #}
+{%- endmacro -%}
!
-{% set ip_prefix = 'ip' %}
-{% set ipv6_prefix = 'ipv6' %}
+{% set ip_prefix = 'ip ' %}
+{% set ipv6_prefix = 'ipv6 ' %}
{% if vrf is vyos_defined %}
{# We need to add an additional whitespace in front of the prefix #}
{# when VRFs are in use, thus we use a variable for prefix handling #}
-{% set ip_prefix = ' ip' %}
-{% set ipv6_prefix = ' ipv6' %}
+{% set ip_prefix = ' ip ' %}
+{% set ipv6_prefix = ' ipv6 ' %}
vrf {{ vrf }}
{% endif %}
{# IPv4 routing #}
{% if route is vyos_defined %}
{% for prefix, prefix_config in route.items() %}
{{ static_routes(ip_prefix, prefix, prefix_config) }}
-{% endfor %}
+{# j2lint: disable=jinja-statements-delimeter #}
+{%- endfor %}
{% endif %}
{# IPv4 default routes from DHCP interfaces #}
{% if dhcp is vyos_defined %}
@@ -34,6 +100,7 @@ vrf {{ vrf }}
{% if route6 is vyos_defined %}
{% for prefix, prefix_config in route6.items() %}
{{ static_routes(ipv6_prefix, prefix, prefix_config) }}
+{# j2lint: disable=jinja-statements-delimeter #}
{% endfor %}
{% endif %}
{% if vrf is vyos_defined %}
@@ -45,19 +112,31 @@ exit-vrf
{% for table_id, table_config in table.items() %}
{% if table_config.route is vyos_defined %}
{% for prefix, prefix_config in table_config.route.items() %}
-{{ static_routes('ip', prefix, prefix_config, table_id) }}
-{% endfor %}
+{{ static_routes('ip ', prefix, prefix_config, table_id) }}
+{# j2lint: disable=jinja-statements-delimeter #}
+{%- endfor %}
{% endif %}
!
{% if table_config.route6 is vyos_defined %}
{% for prefix, prefix_config in table_config.route6.items() %}
-{{ static_routes('ipv6', prefix, prefix_config, table_id) }}
-{% endfor %}
+{{ static_routes('ipv6 ', prefix, prefix_config, table_id) }}
+{# j2lint: disable=jinja-statements-delimeter #}
+{%- endfor %}
{% endif %}
!
{% endfor %}
{% endif %}
!
+{# Multicast route #}
+{% if mroute is vyos_defined %}
+{% set ip_prefix = 'ip m' %}
+{# IPv4 multicast routing #}
+{% for prefix, prefix_config in mroute.items() %}
+{{ static_routes(ip_prefix, prefix, prefix_config) }}
+{# j2lint: disable=jinja-statements-delimeter #}
+{%- endfor %}
+{% endif %}
+!
{% if route_map is vyos_defined %}
ip protocol static route-map {{ route_map }}
!
diff --git a/data/templates/frr/zebra.route-map.frr.j2 b/data/templates/frr/zebra.route-map.frr.j2
index 669d58354..0d6d01930 100644
--- a/data/templates/frr/zebra.route-map.frr.j2
+++ b/data/templates/frr/zebra.route-map.frr.j2
@@ -1,4 +1,12 @@
!
+{{ 'no ' if disable_forwarding is vyos_defined }}{{ afi }} forwarding
+!
+{% if import_table is vyos_defined %}
+{% for table_num, table_config in import_table.items() %}
+ip import-table {{ table_num }} {{ 'distance ' ~ table_config.distance if table_config.distance is vyos_defined }} {{ 'route-map ' ~ table_config.route_map if table_config.route_map is vyos_defined }}
+{% endfor %}
+{% endif %}
+!
{% if nht.no_resolve_via_default is vyos_defined %}
no {{ afi }} nht resolve-via-default
{% endif %}
diff --git a/data/templates/frr/zebra.segment_routing.frr.j2 b/data/templates/frr/zebra.segment_routing.frr.j2
index 7b12fcdd0..b3f2a1fbb 100644
--- a/data/templates/frr/zebra.segment_routing.frr.j2
+++ b/data/templates/frr/zebra.segment_routing.frr.j2
@@ -1,20 +1,69 @@
!
-{% if srv6.locator is vyos_defined %}
segment-routing
+{% if traffic_engineering is vyos_defined %}
+ traffic-eng
+ mpls-te on
+{% if traffic_engineering.database_import_protocol is vyos_defined %}
+{% for protocol, protocol_config in traffic_engineering.database_import_protocol.items() %}
+ mpls-te import {{ protocol | replace('ospf', 'ospfv2') }}
+{% endfor %}
+{% endif %}
+{% if traffic_engineering.segment_list is vyos_defined %}
+{% for segment_list, segment_list_config in traffic_engineering.segment_list.items() %}
+ segment-list {{ segment_list }}
+{% if segment_list_config.index.items() is vyos_defined %}
+{% for index, index_config in segment_list_config.index.items() %}
+{% if index_config.mpls.label is vyos_defined %}
+ index {{ index }} mpls label {{ index_config.mpls.label }}
+{% endif %}
+{% if index_config.nai is vyos_defined %}
+{% if index_config.nai.adjacency is vyos_defined %}
+{% for address_family, address_family_options in index_config.nai.adjacency.items() %}
+ index {{ index }} nai adjacency {{ address_family_options.source_identifier }} {{ address_family_options.destination_identifier }}
+{% endfor %}
+{% endif %}
+{% if index_config.nai.prefix is vyos_defined %}
+{% for address_family, address_family_options in index_config.nai.prefix.items() %}
+{% for prefix, prefix_options in address_family_options.prefix_identifier.items() %}
+ index {{ index }} nai prefix {{ prefix }} {{ 'algorithm 0' if prefix_options.algorithm.spf is vyos_defined }} {{ 'algorithm 1' if prefix_options.algorithm.strict_spf is vyos_defined }}
+{% endfor %}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% endfor %}
+{% endif %}
+ exit
+{% endif %}
+!
+{% if srv6 is vyos_defined %}
srv6
+{% if srv6.encapsulation is vyos_defined %}
+ encapsulation
+{% if srv6.encapsulation.source_address is vyos_defined %}
+ source-address {{ srv6.encapsulation.source_address }}
+{% endif %}
+ exit
+{% endif %}
+{% if srv6.locator is vyos_defined %}
locators
-{% for locator, locator_config in srv6.locator.items() %}
+{% for locator, locator_config in srv6.locator.items() %}
locator {{ locator }}
-{% if locator_config.prefix is vyos_defined %}
+{% if locator_config.prefix is vyos_defined %}
prefix {{ locator_config.prefix }} block-len {{ locator_config.block_len }} node-len {{ locator_config.node_len }} func-bits {{ locator_config.func_bits }}
-{% endif %}
-{% if locator_config.behavior_usid is vyos_defined %}
+{% endif %}
+{% if locator_config.behavior_usid is vyos_defined %}
behavior usid
-{% endif %}
+{% endif %}
+{% if locator_config.format is vyos_defined %}
+ format {{ locator_config.format }}
+{% endif %}
exit
!
-{% endfor %}
+{% endfor %}
exit
+{% endif %}
!
exit
!
diff --git a/data/templates/frr/zebra.traffic_engineering.frr.j2 b/data/templates/frr/zebra.traffic_engineering.frr.j2
new file mode 100644
index 000000000..fee41a898
--- /dev/null
+++ b/data/templates/frr/zebra.traffic_engineering.frr.j2
@@ -0,0 +1,37 @@
+{% if interface is vyos_defined %}
+!
+{% set ns = namespace(mask_by_admin_group=dict()) %}
+{% if admin_group is vyos_defined %}
+{% for ag in admin_group %}
+{% set _ = ns.mask_by_admin_group.update({ag: 1.__lshift__(admin_group[ag]['bit_position'] | int)}) %}
+{% endfor %}
+{% endif %}
+{% set mbit_per_second_2_byte_per_second = 1024 * 1024 / 8 %}
+{% for ifname, data in interface.items() %}
+interface {{ ifname }}
+ link-params
+{% if data.metric is vyos_defined %}
+ metric {{ data.metric }}
+{% endif %}
+{% if data.admin_group is vyos_defined %}
+{% set val = namespace(x=0) %}
+{% for ag in data.admin_group %}
+{% set val.x = (val.x | int).__or__(ns.mask_by_admin_group[ag]) %}
+{% endfor %}
+ admin-grp {{ '0x{:x}'.format(val.x) }}
+{% endif %}
+{% if data.max_bandwidth is vyos_defined %}
+ max-bw {{ (data.max_bandwidth | int) * mbit_per_second_2_byte_per_second }}
+{% endif %}
+{% if data.max_reservable_bandwidth is vyos_defined %}
+{% set v = (data.max_reservable_bandwidth | int) * mbit_per_second_2_byte_per_second %}
+ max-rsv-bw {{ v }}
+{% for i in range(8) %}
+ unrsv-bw {{ i }} {{ v }}
+{% endfor %}
+{% endif %}
+ exit-link-params
+exit
+!
+{% endfor %}
+{% endif %}
diff --git a/data/templates/frr/zebra.vrf.route-map.frr.j2 b/data/templates/frr/zebra.vrf.route-map.frr.j2
index 8ebb82511..656b31deb 100644
--- a/data/templates/frr/zebra.vrf.route-map.frr.j2
+++ b/data/templates/frr/zebra.vrf.route-map.frr.j2
@@ -25,6 +25,6 @@ vrf {{ vrf }}
vni {{ vrf_config.vni }}
{% endif %}
exit-vrf
-{% endfor %}
!
+{% endfor %}
{% endif %}
diff --git a/data/templates/getty/serial-getty.service.j2 b/data/templates/getty/serial-getty.service.j2
index 0183eae7d..687b05b6d 100644
--- a/data/templates/getty/serial-getty.service.j2
+++ b/data/templates/getty/serial-getty.service.j2
@@ -22,7 +22,7 @@ Before=rescue.service
# The '-o' option value tells agetty to replace 'login' arguments with an
# option to preserve environment (-p), followed by '--' for safety, and then
# the entered username.
-ExecStart=-/sbin/agetty -o '-p -- \\u' --keep-baud {{ speed }} %I $TERM
+ExecStart=-/sbin/agetty -o '-p -- \\u' %I {{ speed }} $TERM
Type=idle
Restart=always
UtmpIdentifier=%I
diff --git a/data/templates/grub/grub_common.j2 b/data/templates/grub/grub_common.j2
index 5e9b95cc0..c4c4adf10 100644
--- a/data/templates/grub/grub_common.j2
+++ b/data/templates/grub/grub_common.j2
@@ -7,7 +7,7 @@ fi
# create and activate serial console
function setup_serial {
# initialize the first serial port by default
- if [ "${console_type}" == "ttyS" ]; then
+ if [ "${console_type}" == "ttyS" -o "${console_type}" == "ttyAMA" ]; then
if [ "${console_num}" == "0" ]; then
serial --unit=0 --speed=${console_speed}
else
diff --git a/data/templates/grub/grub_compat.j2 b/data/templates/grub/grub_compat.j2
index 8fb4f71dc..7f930a11f 100644
--- a/data/templates/grub/grub_compat.j2
+++ b/data/templates/grub/grub_compat.j2
@@ -12,7 +12,7 @@
{% macro console_name(type) -%}
{% if type == 'tty' -%}
KVM
-{%- elif type == 'ttyS' -%}
+{%- elif type == 'ttyS' or type == 'ttyAMA' -%}
Serial
{%- else -%}
Unknown
@@ -23,6 +23,8 @@
console=ttyS0,{{ console_speed }} console=tty0
{%- elif type == 'ttyS' -%}
console=tty0 console=ttyS0,{{ console_speed }}
+{%- elif type == 'ttyAMA' -%}
+ console=tty0 console=ttyAMA0,{{ console_speed }}
{%- else -%}
console=tty0 console=ttyS0,{{ console_speed }}
{%- endif %}
diff --git a/data/templates/grub/grub_options.j2 b/data/templates/grub/grub_options.j2
index a00bf4e37..43099cc51 100644
--- a/data/templates/grub/grub_options.j2
+++ b/data/templates/grub/grub_options.j2
@@ -28,7 +28,12 @@ submenu "Boot options" {
configfile ${prefix}/grub.cfg.d/*vyos-menu*.cfg
}
menuentry "ttyS (serial)" {
- set console_type="ttyS"
+ if [ "${grub_cpu}" == "arm64" ]; then
+ set serial_console="ttyAMA"
+ else
+ set serial_console="ttyS"
+ fi
+ set console_type="$serial_console"
export console_type
setup_serial
configfile ${prefix}/grub.cfg.d/*vyos-menu*.cfg
diff --git a/data/templates/grub/grub_vyos_version.j2 b/data/templates/grub/grub_vyos_version.j2
index de85f1419..c546670c2 100644
--- a/data/templates/grub/grub_vyos_version.j2
+++ b/data/templates/grub/grub_vyos_version.j2
@@ -11,7 +11,7 @@
{% endif %}
menuentry "{{ version_name }}" --id {{ version_uuid }} {
set boot_opts="{{ boot_opts_rendered }}"
- if [ "${console_type}" == "ttyS" ]; then
+ if [ "${console_type}" == "ttyS" -o "${console_type}" == "ttyAMA" ]; then
set console_opts="console=${console_type}${console_num},${console_speed}"
else
set console_opts="console=${console_type}${console_num}"
diff --git a/data/templates/high-availability/keepalived.conf.j2 b/data/templates/high-availability/keepalived.conf.j2
index c0d66ae54..f69230f8b 100644
--- a/data/templates/high-availability/keepalived.conf.j2
+++ b/data/templates/high-availability/keepalived.conf.j2
@@ -5,6 +5,9 @@
# Global definitions configuration block
global_defs {
dynamic_interfaces
+{% if vrrp.snmp.trap is vyos_defined %}
+ enable_traps
+{% endif %}
script_user root
{% if vrrp.global_parameters.startup_delay is vyos_defined %}
vrrp_startup_delay {{ vrrp.global_parameters.startup_delay }}
@@ -44,6 +47,9 @@ vrrp_script healthcheck_sg_{{ name }} {
script "/usr/bin/ping -c1 {{ sync_group_config.health_check.ping }}"
{% endif %}
interval {{ sync_group_config.health_check.interval }}
+{% if sync_group_config.health_check.timeout is vyos_defined %}
+ timeout {{ sync_group_config.health_check.timeout }}
+{% endif %}
fall {{ sync_group_config.health_check.failure_count }}
rise 1
}
@@ -61,6 +67,9 @@ vrrp_script healthcheck_{{ name }} {
script "/usr/bin/ping -c1 {{ group_config.health_check.ping }}"
{% endif %}
interval {{ group_config.health_check.interval }}
+{% if group_config.health_check.timeout is vyos_defined %}
+ timeout {{ group_config.health_check.timeout }}
+{% endif %}
fall {{ group_config.health_check.failure_count }}
rise 1
}
@@ -219,7 +228,9 @@ virtual_server fwmark {{ vserver_config.fwmark }} {
{% elif vserver_config.forward_method is vyos_defined('tunnel') %}
lb_kind TUN
{% endif %}
+{% if vserver_config.persistence_timeout | int > 0 %}
persistence_timeout {{ vserver_config.persistence_timeout }}
+{% endif %}
protocol {{ vserver_config.protocol | upper }}
{% if vserver_config.real_server is vyos_defined %}
{% for rserver, rserver_config in vserver_config.real_server.items() %}
diff --git a/data/templates/https/nginx.default.j2 b/data/templates/https/nginx.default.j2
index 1dde66ebf..cf87fb309 100644
--- a/data/templates/https/nginx.default.j2
+++ b/data/templates/https/nginx.default.j2
@@ -18,6 +18,7 @@ server {
listen [::]:{{ port }} ssl;
{% endif %}
+ server_tokens off;
server_name {{ hostname }};
root /srv/localui;
@@ -48,7 +49,7 @@ server {
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK';
# proxy settings for HTTP API, if enabled; 503, if not
- location ~ ^/(retrieve|configure|config-file|image|import-pki|container-image|generate|show|reboot|reset|poweroff|docs|openapi.json|redoc|graphql) {
+ location ~ ^/(retrieve|configure|config-file|image|import-pki|container-image|generate|show|reboot|reset|poweroff|traceroute|info|docs|openapi.json|redoc|graphql|renew) {
{% if api is vyos_defined %}
proxy_pass http://unix:/run/api.sock;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
diff --git a/data/templates/ids/fastnetmon.j2 b/data/templates/ids/fastnetmon.j2
deleted file mode 100644
index f6f03d0db..000000000
--- a/data/templates/ids/fastnetmon.j2
+++ /dev/null
@@ -1,121 +0,0 @@
-# enable this option if you want to send logs to local syslog facility
-logging:logging_level = debug
-logging:local_syslog_logging = on
-
-# list of all your networks in CIDR format
-networks_list_path = /run/fastnetmon/networks_list
-
-# list networks in CIDR format which will be not monitored for attacks
-white_list_path = /run/fastnetmon/excluded_networks_list
-
-# Enable/Disable any actions in case of attack
-enable_ban = on
-enable_ban_ipv6 = on
-
-## How many packets will be collected from attack traffic
-ban_details_records_count = 500
-
-## How long (in seconds) we should keep an IP in blocked state
-## If you set 0 here it completely disables unban capability
-{% if ban_time is vyos_defined %}
-ban_time = {{ ban_time }}
-{% endif %}
-
-# Check if the attack is still active, before triggering an unban callback with this option
-# If the attack is still active, check each run of the unban watchdog
-unban_only_if_attack_finished = on
-
-# enable per subnet speed meters
-# For each subnet, list track speed in bps and pps for both directions
-enable_subnet_counters = off
-
-{% if mode is vyos_defined('mirror') %}
-mirror_afpacket = on
-{% elif mode is vyos_defined('sflow') %}
-sflow = on
-{% if sflow.port is vyos_defined %}
-sflow_port = {{ sflow.port }}
-{% endif %}
-{% if sflow.listen_address is vyos_defined %}
-sflow_host = {{ sflow.listen_address }}
-{% endif %}
-{% endif %}
-
-
-process_incoming_traffic = {{ 'on' if direction is vyos_defined and 'in' in direction else 'off' }}
-process_outgoing_traffic = {{ 'on' if direction is vyos_defined and 'out' in direction else 'off' }}
-
-{% if threshold is vyos_defined %}
-{% if threshold.general is vyos_defined %}
-# General threshold
-{% for thr, thr_value in threshold.general.items() %}
-{% if thr is vyos_defined('fps') %}
-ban_for_flows = on
-threshold_flows = {{ thr_value }}
-{% elif thr is vyos_defined('mbps') %}
-ban_for_bandwidth = on
-threshold_mbps = {{ thr_value }}
-{% elif thr is vyos_defined('pps') %}
-ban_for_pps = on
-threshold_pps = {{ thr_value }}
-{% endif %}
-{% endfor %}
-{% endif %}
-
-{% if threshold.tcp is vyos_defined %}
-# TCP threshold
-{% for thr, thr_value in threshold.tcp.items() %}
-{% if thr is vyos_defined('fps') %}
-ban_for_tcp_flows = on
-threshold_tcp_flows = {{ thr_value }}
-{% elif thr is vyos_defined('mbps') %}
-ban_for_tcp_bandwidth = on
-threshold_tcp_mbps = {{ thr_value }}
-{% elif thr is vyos_defined('pps') %}
-ban_for_tcp_pps = on
-threshold_tcp_pps = {{ thr_value }}
-{% endif %}
-{% endfor %}
-{% endif %}
-
-{% if threshold.udp is vyos_defined %}
-# UDP threshold
-{% for thr, thr_value in threshold.udp.items() %}
-{% if thr is vyos_defined('fps') %}
-ban_for_udp_flows = on
-threshold_udp_flows = {{ thr_value }}
-{% elif thr is vyos_defined('mbps') %}
-ban_for_udp_bandwidth = on
-threshold_udp_mbps = {{ thr_value }}
-{% elif thr is vyos_defined('pps') %}
-ban_for_udp_pps = on
-threshold_udp_pps = {{ thr_value }}
-{% endif %}
-{% endfor %}
-{% endif %}
-
-{% if threshold.icmp is vyos_defined %}
-# ICMP threshold
-{% for thr, thr_value in threshold.icmp.items() %}
-{% if thr is vyos_defined('fps') %}
-ban_for_icmp_flows = on
-threshold_icmp_flows = {{ thr_value }}
-{% elif thr is vyos_defined('mbps') %}
-ban_for_icmp_bandwidth = on
-threshold_icmp_mbps = {{ thr_value }}
-{% elif thr is vyos_defined('pps') %}
-ban_for_icmp_pps = on
-threshold_icmp_pps = {{ thr_value }}
-{% endif %}
-{% endfor %}
-{% endif %}
-
-{% endif %}
-
-{% if listen_interface is vyos_defined %}
-interfaces = {{ listen_interface | join(',') }}
-{% endif %}
-
-{% if alert_script is vyos_defined %}
-notify_script_path = {{ alert_script }}
-{% endif %}
diff --git a/data/templates/ids/fastnetmon_excluded_networks_list.j2 b/data/templates/ids/fastnetmon_excluded_networks_list.j2
deleted file mode 100644
index c88a1c527..000000000
--- a/data/templates/ids/fastnetmon_excluded_networks_list.j2
+++ /dev/null
@@ -1,5 +0,0 @@
-{% if excluded_network is vyos_defined %}
-{% for net in excluded_network %}
-{{ net }}
-{% endfor %}
-{% endif %}
diff --git a/data/templates/ids/fastnetmon_networks_list.j2 b/data/templates/ids/fastnetmon_networks_list.j2
deleted file mode 100644
index 0a0576d2a..000000000
--- a/data/templates/ids/fastnetmon_networks_list.j2
+++ /dev/null
@@ -1,5 +0,0 @@
-{% if network is vyos_defined %}
-{% for net in network %}
-{{ net }}
-{% endfor %}
-{% endif %}
diff --git a/data/templates/igmp-proxy/igmpproxy.conf.j2 b/data/templates/igmp-proxy/igmpproxy.conf.j2
index 85a04de7d..6e0d691ea 100644
--- a/data/templates/igmp-proxy/igmpproxy.conf.j2
+++ b/data/templates/igmp-proxy/igmpproxy.conf.j2
@@ -9,7 +9,7 @@
# option can be used in order to define legal multicast sources.
#
# The "quickleave" should be used to avoid saturation of the upstream link. The
-# option should only be used if it's absolutely nessecary to accurately imitate
+# option should only be used if it's absolutely necessary to accurately imitate
# just one Client.
#
########################################################
diff --git a/data/templates/ipsec/charon.j2 b/data/templates/ipsec/charon.j2
index 388559af8..bafdaf157 100644
--- a/data/templates/ipsec/charon.j2
+++ b/data/templates/ipsec/charon.j2
@@ -6,7 +6,7 @@ charon {
# Maximum number of half-open IKE_SAs for a single peer IP.
# block_threshold = 5
- # Whether Certicate Revocation Lists (CRLs) fetched via HTTP or LDAP should
+ # Whether Certificate Revocation Lists (CRLs) fetched via HTTP or LDAP should
# be saved under a unique file name derived from the public key of the
# Certification Authority (CA) to /etc/ipsec.d/crls (stroke) or
# /etc/swanctl/x509crl (vici), respectively.
@@ -202,15 +202,16 @@ charon {
# Size of the AH/ESP replay window, in packets.
# replay_window = 32
- # Base to use for calculating exponential back off, see IKEv2 RETRANSMISSION
- # in strongswan.conf(5).
- # retransmit_base = 1.8
-
- # Timeout in seconds before sending first retransmit.
- # retransmit_timeout = 4.0
-
- # Number of times to retransmit a packet before giving up.
- # retransmit_tries = 5
+ # IKEv2 RETRANSMISSION
+{% if options.retransmission.attempts is vyos_defined %}
+ retransmit_tries = {{ options.retransmission.attempts }}
+{% endif %}
+{% if options.retransmission.base is vyos_defined %}
+ retransmit_base = {{ options.retransmission.base }}
+{% endif %}
+{% if options.retransmission.timeout is vyos_defined %}
+ retransmit_timeout = {{ options.retransmission.timeout }}
+{% endif %}
# Interval in seconds to use when retrying to initiate an IKE_SA (e.g. if
# DNS resolution failed), 0 to disable retries.
diff --git a/data/templates/ipsec/charon_logging.conf.j2 b/data/templates/ipsec/charon_logging.conf.j2
new file mode 100644
index 000000000..e8edee817
--- /dev/null
+++ b/data/templates/ipsec/charon_logging.conf.j2
@@ -0,0 +1,18 @@
+# Generated by ${vyos_conf_scripts_dir}/vpn_ipsec.py
+
+charon {
+ syslog {
+ # prefix for each log message
+ identifier = charon
+ # use default settings to log to the LOG_DAEMON facility
+ daemon {
+{% if log.level is vyos_defined %}
+ # Disabled - logging handled exclusively by charon-systemd.conf
+ default = -1
+{% else %}
+ default = 1
+{% endif %}
+ ike_name = yes
+ }
+ }
+}
diff --git a/data/templates/ipsec/charon_systemd.conf.j2 b/data/templates/ipsec/charon_systemd.conf.j2
new file mode 100644
index 000000000..368aa1ae3
--- /dev/null
+++ b/data/templates/ipsec/charon_systemd.conf.j2
@@ -0,0 +1,18 @@
+# Generated by ${vyos_conf_scripts_dir}/vpn_ipsec.py
+
+charon-systemd {
+
+ # Section to configure native systemd journal logger, very similar to the
+ # syslog logger as described in LOGGER CONFIGURATION in strongswan.conf(5).
+ journal {
+
+ # Loglevel for a specific subsystem.
+ # <subsystem> = <default>
+
+{% if log.level is vyos_defined %}
+ # Default loglevel.
+ default = {{ log.level }}
+{% endif %}
+ }
+
+}
diff --git a/data/templates/ipsec/ios_profile.j2 b/data/templates/ipsec/ios_profile.j2
index 966fad433..6993f82bf 100644
--- a/data/templates/ipsec/ios_profile.j2
+++ b/data/templates/ipsec/ios_profile.j2
@@ -55,11 +55,9 @@
<!-- The server is authenticated using a certificate -->
<key>AuthenticationMethod</key>
<string>Certificate</string>
-{% if authentication.client_mode.startswith("eap") %}
<!-- The client uses EAP to authenticate -->
<key>ExtendedAuthEnabled</key>
<integer>1</integer>
-{% endif %}
<!-- The next two dictionaries are optional (as are the keys in them), but it is recommended to specify them as the default is to use 3DES.
IMPORTANT: Because only one proposal is sent (even if nothing is configured here) it must match the server configuration -->
<key>IKESecurityAssociationParameters</key>
@@ -80,9 +78,9 @@
<string>{{ esp_encryption.encryption }}</string>
<key>IntegrityAlgorithm</key>
<string>{{ esp_encryption.hash }}</string>
-{% if esp_encryption.pfs is vyos_defined %}
+{% if ike_encryption.dh_group is vyos_defined %}
<key>DiffieHellmanGroup</key>
- <integer>{{ esp_encryption.pfs }}</integer>
+ <integer>{{ ike_encryption.dh_group }}</integer>
{% endif %}
</dict>
<!-- Controls whether the client offers Perfect Forward Secrecy (PFS). This should be set to match the server. -->
diff --git a/data/templates/ipsec/swanctl.conf.j2 b/data/templates/ipsec/swanctl.conf.j2
index 698a9135e..6e143d5be 100644
--- a/data/templates/ipsec/swanctl.conf.j2
+++ b/data/templates/ipsec/swanctl.conf.j2
@@ -4,15 +4,17 @@
{% import 'ipsec/swanctl/peer.j2' as peer_tmpl %}
{% import 'ipsec/swanctl/remote_access.j2' as remote_access_tmpl %}
+{% set uniqreqids = 'never' if disable_uniqreqids is vyos_defined else None %}
+
connections {
{% if profile is vyos_defined %}
{% for name, profile_conf in profile.items() if profile_conf.disable is not vyos_defined and profile_conf.bind.tunnel is vyos_defined %}
-{{ profile_tmpl.conn(name, profile_conf, ike_group, esp_group) }}
+{{ profile_tmpl.conn(name, profile_conf, ike_group, esp_group, uniqreqids) }}
{% endfor %}
{% endif %}
{% if site_to_site.peer is vyos_defined %}
{% for peer, peer_conf in site_to_site.peer.items() if peer not in dhcp_no_address and peer_conf.disable is not vyos_defined %}
-{{ peer_tmpl.conn(peer, peer_conf, ike_group, esp_group) }}
+{{ peer_tmpl.conn(peer, peer_conf, ike_group, esp_group, uniqreqids) }}
{% endfor %}
{% endif %}
{% if remote_access.connection is vyos_defined %}
@@ -21,7 +23,7 @@ connections {
{% endfor %}
{% endif %}
{% if l2tp %}
-{{ l2tp_tmpl.conn(l2tp, l2tp_outside_address, l2tp_ike_default, l2tp_esp_default, ike_group, esp_group) }}
+{{ l2tp_tmpl.conn(l2tp, l2tp_outside_address, l2tp_ike_default, l2tp_esp_default, ike_group, esp_group, uniqreqids) }}
{% endif %}
}
@@ -87,7 +89,34 @@ secrets {
id-{{ gen_uuid }} = "{{ id }}"
{% endfor %}
{% endif %}
+{% if psk_config.secret_type is vyos_defined('base64') %}
+ secret = 0s{{ psk_config.secret }}
+{% elif psk_config.secret_type is vyos_defined('hex') %}
+ secret = 0x{{ psk_config.secret }}
+{% elif psk_config.secret_type is vyos_defined('plaintext') %}
secret = "{{ psk_config.secret }}"
+{% endif %}
+ }
+{% endfor %}
+{% endif %}
+
+{% if authentication.ppk is vyos_defined %}
+{% for ppk, ppk_config in authentication.ppk.items() %}
+ ppk-{{ ppk }} {
+{% if ppk_config.id is vyos_defined %}
+ # ID's from auth ppk <tag> id xxx
+{% for id in ppk_config.id %}
+{% set gen_uuid = '' | generate_uuid4 %}
+ id-{{ gen_uuid }} = "{{ id }}"
+{% endfor %}
+{% endif %}
+{% if ppk_config.secret_type is vyos_defined('base64') %}
+ secret = 0s{{ ppk_config.secret }}
+{% elif ppk_config.secret_type is vyos_defined('hex') %}
+ secret = 0x{{ ppk_config.secret }}
+{% elif ppk_config.secret_type is vyos_defined('plaintext') %}
+ secret = "{{ ppk_config.secret }}"
+{% endif %}
}
{% endfor %}
{% endif %}
diff --git a/data/templates/ipsec/swanctl/l2tp.j2 b/data/templates/ipsec/swanctl/l2tp.j2
index 7e63865cc..7eaf9087d 100644
--- a/data/templates/ipsec/swanctl/l2tp.j2
+++ b/data/templates/ipsec/swanctl/l2tp.j2
@@ -1,4 +1,4 @@
-{% macro conn(l2tp, l2tp_outside_address, l2tp_ike_default, l2tp_esp_default, ike_group, esp_group) %}
+{% macro conn(l2tp, l2tp_outside_address, l2tp_ike_default, l2tp_esp_default, ike_group, esp_group, uniqreqids) %}
{% set l2tp_ike = ike_group[l2tp.ike_group] if l2tp.ike_group is vyos_defined else None %}
{% set l2tp_esp = esp_group[l2tp.esp_group] if l2tp.esp_group is vyos_defined else None %}
l2tp_remote_access {
@@ -8,6 +8,9 @@
dpd_timeout = 45s
rekey_time = {{ l2tp_ike.lifetime if l2tp_ike else l2tp.ike_lifetime }}s
reauth_time = 0
+{% if uniqreqids is vyos_defined %}
+ unique = {{ uniqreqids }}
+{% endif %}
local {
auth = {{ 'psk' if l2tp.authentication.mode == 'pre-shared-secret' else 'pubkey' }}
{% if l2tp.authentication.mode == 'x509' %}
diff --git a/data/templates/ipsec/swanctl/peer.j2 b/data/templates/ipsec/swanctl/peer.j2
index 3a9af2c94..96f761cce 100644
--- a/data/templates/ipsec/swanctl/peer.j2
+++ b/data/templates/ipsec/swanctl/peer.j2
@@ -1,8 +1,24 @@
-{% macro conn(peer, peer_conf, ike_group, esp_group) %}
+{% macro conn(peer, peer_conf, ike_group, esp_group, uniqreqids) %}
{% set name = peer.replace("@", "") | dot_colon_to_dash %}
{# peer needs to reference the global IKE configuration for certain values #}
{% set ike = ike_group[peer_conf.ike_group] %}
{{ name }} {
+{# Resolve effective reauth setting: peer overrides ike-group #}
+{% set reauth = peer_conf.ikev2_reauth if peer_conf.ikev2_reauth is vyos_defined else '' %}
+{% if reauth == 'inherit' %}
+{% set reauth = ike.ikev2_reauth is vyos_defined %}
+{% else %}
+{% set reauth = reauth == 'yes' %}
+{% endif %}
+{% if peer_conf.authentication.ppk.id is vyos_defined %}
+ ppk_id = {{ peer_conf.authentication.ppk.id }}
+{% endif %}
+{% if peer_conf.authentication.ppk.required is vyos_defined %}
+ ppk_required = yes
+{% endif %}
+{% if peer_conf.childless is vyos_defined %}
+ childless = {{ peer_conf.childless }}
+{% endif %}
proposals = {{ ike | get_esp_ike_cipher | join(',') }}
version = {{ ike.key_exchange[4:] if ike.key_exchange is vyos_defined else "0" }}
{% if peer_conf.virtual_address is vyos_defined %}
@@ -27,12 +43,18 @@
reauth_time = 0
{% elif peer_conf.connection_type is not vyos_defined or peer_conf.connection_type is vyos_defined('initiate') %}
keyingtries = 0
-{% elif peer_conf.connection_type is vyos_defined('respond') %}
+{% if reauth and ike.key_exchange is vyos_defined('ikev2') %}
+ reauth_time = {{ ike.lifetime }}s
+{% endif %}
+{% elif peer_conf.connection_type is vyos_defined('trap') %}
keyingtries = 1
{% endif %}
{% if peer_conf.force_udp_encapsulation is vyos_defined %}
encap = yes
{% endif %}
+{% if uniqreqids is vyos_defined %}
+ unique = {{ uniqreqids }}
+{% endif %}
local {
{% if peer_conf.authentication.local_id is vyos_defined %}
id = "{{ peer_conf.authentication.local_id }}"
@@ -68,8 +90,19 @@
rekey_packets = 0
rekey_time = 0s
{% endif %}
- local_ts = 0.0.0.0/0,::/0
- remote_ts = 0.0.0.0/0,::/0
+{# set default traffic-selectors #}
+{% set local_ts = '0.0.0.0/0,::/0' %}
+{% set remote_ts = '0.0.0.0/0,::/0' %}
+{% if peer_conf.vti.traffic_selector is vyos_defined %}
+{% if peer_conf.vti.traffic_selector.local is vyos_defined and peer_conf.vti.traffic_selector.local.prefix is vyos_defined %}
+{% set local_ts = peer_conf.vti.traffic_selector.local.prefix | join(',') %}
+{% endif %}
+{% if peer_conf.vti.traffic_selector.remote is vyos_defined and peer_conf.vti.traffic_selector.remote.prefix is vyos_defined %}
+{% set remote_ts = peer_conf.vti.traffic_selector.remote.prefix | join(',') %}
+{% endif %}
+{% endif %}
+ local_ts = {{ local_ts }}
+ remote_ts = {{ remote_ts }}
updown = "/etc/ipsec.d/vti-up-down {{ peer_conf.vti.bind }}"
{# The key defaults to 0 and will match any policies which similarly do not have a lookup key configuration. #}
{# Thus we simply shift the key by one to also support a vti0 interface #}
@@ -82,7 +115,7 @@
start_action = none
{% elif peer_conf.connection_type is not vyos_defined or peer_conf.connection_type is vyos_defined('initiate') %}
start_action = start
-{% elif peer_conf.connection_type is vyos_defined('respond') %}
+{% elif peer_conf.connection_type is vyos_defined('trap') %}
start_action = trap
{% elif peer_conf.connection_type is vyos_defined('none') %}
start_action = none
@@ -100,6 +133,12 @@
{% set tunnel_esp_name = tunnel_conf.esp_group if tunnel_conf.esp_group is vyos_defined else peer_conf.default_esp_group %}
{% set tunnel_esp = esp_group[tunnel_esp_name] %}
{% set proto = tunnel_conf.protocol if tunnel_conf.protocol is vyos_defined else '' %}
+{# VyOS 1.3.x (with strongSwan 5.7.x) previously allowed using `all` in traffic selectors, converting it to `%any`. #}
+{# In strongSwan 5.9.x (VyOS >= 1.4.x), the syntax `x.x.x.0/24[all/]` is no longer accepted. #}
+{# We must now explicitly specify a protocol (e.g., `tcp`, `udp`). #}
+{# To achieve "all" protocol behavior, simply use the subnet notation without brackets, #}
+{# such as `x.x.x.0/24` or `x.x.x.0/24[/443]`. #}
+{% set proto = '' if proto == 'all' else proto %}
{% set local_port = tunnel_conf.local.port if tunnel_conf.local.port is vyos_defined else '' %}
{% set local_suffix = '[{0}/{1}]'.format(proto, local_port) if proto or local_port else '' %}
{% set remote_port = tunnel_conf.remote.port if tunnel_conf.remote.port is vyos_defined else '' %}
@@ -140,7 +179,7 @@
start_action = none
{% elif peer_conf.connection_type is not vyos_defined or peer_conf.connection_type is vyos_defined('initiate') %}
start_action = start
-{% elif peer_conf.connection_type is vyos_defined('respond') %}
+{% elif peer_conf.connection_type is vyos_defined('trap') %}
start_action = trap
{% elif peer_conf.connection_type is vyos_defined('none') %}
start_action = none
diff --git a/data/templates/ipsec/swanctl/profile.j2 b/data/templates/ipsec/swanctl/profile.j2
index 8519a84f8..10fe0a8ec 100644
--- a/data/templates/ipsec/swanctl/profile.j2
+++ b/data/templates/ipsec/swanctl/profile.j2
@@ -1,4 +1,4 @@
-{% macro conn(name, profile_conf, ike_group, esp_group) %}
+{% macro conn(name, profile_conf, ike_group, esp_group, uniqreqids) %}
{# peer needs to reference the global IKE configuration for certain values #}
{% set ike = ike_group[profile_conf.ike_group] %}
{% set esp = esp_group[profile_conf.esp_group] %}
@@ -13,6 +13,9 @@
dpd_timeout = {{ ike.dead_peer_detection.timeout }}
dpd_delay = {{ ike.dead_peer_detection.interval }}
{% endif %}
+{% if uniqreqids is vyos_defined %}
+ unique = {{ uniqreqids }}
+{% endif %}
{% if profile_conf.authentication.mode is vyos_defined('pre-shared-secret') %}
local {
auth = psk
@@ -22,16 +25,16 @@
}
{% endif %}
children {
- dmvpn {
+ dmvpn-{{ name }}-{{ interface }}-child {
esp_proposals = {{ esp | get_esp_ike_cipher(ike) | join(',') }}
rekey_time = {{ esp.lifetime }}s
rand_time = 540s
local_ts = dynamic[gre]
remote_ts = dynamic[gre]
mode = {{ esp.mode }}
-{% if ike.dead_peer_detection.action is vyos_defined %}
- dpd_action = {{ ike.dead_peer_detection.action }}
-{% endif %}
+ dpd_action = clear
+ close_action = none
+ start_action = none
{% if esp.compression is vyos_defined('enable') %}
ipcomp = yes
{% endif %}
diff --git a/data/templates/ipsec/swanctl/remote_access.j2 b/data/templates/ipsec/swanctl/remote_access.j2
index c79f292b4..639248caf 100644
--- a/data/templates/ipsec/swanctl/remote_access.j2
+++ b/data/templates/ipsec/swanctl/remote_access.j2
@@ -3,11 +3,23 @@
{% set ike = ike_group[rw_conf.ike_group] %}
{% set esp = esp_group[rw_conf.esp_group] %}
ra-{{ name }} {
+{% if rw_conf.authentication.ppk.id is vyos_defined %}
+ ppk_id = {{ rw_conf.authentication.ppk.id }}
+{% endif %}
+{% if rw_conf.authentication.ppk.required is vyos_defined %}
+ ppk_required = yes
+{% endif %}
+{% if rw_conf.childless is vyos_defined %}
+ childless = {{ rw_conf.childless }}
+{% endif %}
remote_addrs = %any
local_addrs = {{ rw_conf.local_address if rw_conf.local_address is not vyos_defined('any') else '%any' }} # dhcp:{{ rw_conf.dhcp_interface if rw_conf.dhcp_interface is vyos_defined else 'no' }}
proposals = {{ ike_group[rw_conf.ike_group] | get_esp_ike_cipher | join(',') }}
version = {{ ike.key_exchange[4:] if ike.key_exchange is vyos_defined else "0" }}
send_certreq = no
+{% if rw_conf.authentication.always_send_cert is vyos_defined %}
+ send_cert = always
+{% endif %}
{% if ike.dead_peer_detection is vyos_defined %}
dpd_timeout = {{ ike.dead_peer_detection.timeout }}
dpd_delay = {{ ike.dead_peer_detection.interval }}
@@ -67,7 +79,7 @@
{% endif %}
{% set local_prefix = rw_conf.local.prefix if rw_conf.local.prefix is vyos_defined else ['0.0.0.0/0', '::/0'] %}
{% set local_port = rw_conf.local.port if rw_conf.local.port is vyos_defined else '' %}
-{% set local_suffix = '[%any/{1}]'.format(local_port) if local_port else '' %}
+{% set local_suffix = '[%any/{port}]'.format(port=local_port) if local_port else '' %}
local_ts = {{ local_prefix | join(local_suffix + ",") }}{{ local_suffix }}
{% if rw_conf.bind is vyos_defined %}
{# The key defaults to 0 and will match any policies which similarly do not have a lookup key configuration. #}
diff --git a/data/templates/ipt-netflow/ipt_NETFLOW.conf.j2 b/data/templates/ipt-netflow/ipt_NETFLOW.conf.j2
new file mode 100644
index 000000000..116b8c973
--- /dev/null
+++ b/data/templates/ipt-netflow/ipt_NETFLOW.conf.j2
@@ -0,0 +1,29 @@
+{% if netflow.engine_id is vyos_defined %}
+options ipt_NETFLOW engine-id={{ netflow.engine_id }}
+{% endif %}
+{% if netflow.max_flows is vyos_defined %}
+options ipt_NETFLOW maxflows={{ netflow.max_flows }}
+{% endif %}
+{% if netflow.sampling_rate is vyos_defined %}
+options ipt_NETFLOW sampler=random:{{ netflow.sampling_rate }}
+{% endif %}
+{% if netflow.server is vyos_defined %}
+{% set servers_list = [] %}
+{% for server in netflow.server %}
+{% set d = netflow.server[server] %}
+{% set s = (server | bracketize_ipv6) ~ ':' ~ d['port'] %}
+{% set s = s ~ ('%' ~ d['source_interface'] if d['source_interface'] is vyos_defined else '') %}
+{% set s = s ~ ('@' ~ d['source_address'] if d['source_address'] is vyos_defined else '') %}
+{% set _ = servers_list.append(s) %}
+{% endfor %}
+options ipt_NETFLOW destination={{ servers_list | join(",") }}
+{% endif %}
+{% if netflow.version is vyos_defined %}
+options ipt_NETFLOW protocol={{ netflow.version }}
+{% endif %}
+{% if netflow.inactive_timeout is vyos_defined %}
+options ipt_NETFLOW inactive_timeout={{ netflow.inactive_timeout }}
+{% endif %}
+{% if netflow.active_timeout is vyos_defined %}
+options ipt_NETFLOW active_timeout={{ netflow.active_timeout }}
+{% endif %}
diff --git a/data/templates/lcd/LCDd.conf.j2 b/data/templates/lcd/LCDd.conf.j2
index 3631add1d..456aa79e7 100644
--- a/data/templates/lcd/LCDd.conf.j2
+++ b/data/templates/lcd/LCDd.conf.j2
@@ -55,6 +55,8 @@ Driver=CFontzPacket
Driver=sdeclcd
{% elif model == 'hd44780' %}
Driver=hd44780
+{% elif model == 'mtc-s16209x' %}
+Driver=mtc_s16209x
{% endif %}
{% endif %}
@@ -135,5 +137,10 @@ USB=yes
ConnectionType=ezio
Device={{ device }}
Size=16x2
+{% elif model == 'mtc-s16209x' %}
+[mtc_s16209x]
+Device={{ device }}
+Brightness=255
+Reboot=yes
{% endif %}
{% endif %}
diff --git a/data/templates/lldp/vyos.conf.j2 b/data/templates/lldp/vyos.conf.j2
index 4b4228cea..432a7a8e6 100644
--- a/data/templates/lldp/vyos.conf.j2
+++ b/data/templates/lldp/vyos.conf.j2
@@ -4,7 +4,7 @@ configure system platform VyOS
configure system description "VyOS {{ version }}"
{% if interface is vyos_defined %}
{% set tmp = [] %}
-{% for iface, iface_options in interface.items() if iface_options.disable is not vyos_defined %}
+{% for iface, iface_options in interface.items() %}
{% if iface == 'all' %}
{% set iface = '*' %}
{% endif %}
@@ -17,6 +17,15 @@ configure ports {{ iface }} med location elin "{{ iface_options.location.elin }}
configure ports {{ iface }} med location coordinate latitude "{{ iface_options.location.coordinate_based.latitude }}" longitude "{{ iface_options.location.coordinate_based.longitude }}" altitude "{{ iface_options.location.coordinate_based.altitude }}m" datum "{{ iface_options.location.coordinate_based.datum }}"
{% endif %}
{% endif %}
+{% set mode = iface_options.mode %}
+{% if mode == 'tx' %}
+{% set mode = 'tx-only' %}
+{% elif mode == 'rx' %}
+{% set mode = 'rx-only' %}
+{% elif mode == 'rx-tx' %}
+{% set mode = 'rx-and-tx' %}
+{% endif %}
+configure ports {{ iface }} lldp status {{ mode }}
{% endfor %}
configure system interface pattern "{{ tmp | join(",") }}"
{% endif %}
diff --git a/data/templates/load-balancing/haproxy.cfg.j2 b/data/templates/load-balancing/haproxy.cfg.j2
index 5137966c1..79fb5e369 100644
--- a/data/templates/load-balancing/haproxy.cfg.j2
+++ b/data/templates/load-balancing/haproxy.cfg.j2
@@ -1,4 +1,4 @@
-### Autogenerated by load-balancing_reverse-proxy.py ###
+### Autogenerated by load-balancing_haproxy.py ###
global
chroot /var/lib/haproxy
@@ -38,9 +38,10 @@ defaults
log global
mode http
option dontlognull
- timeout connect 10s
- timeout client 50s
- timeout server 50s
+ timeout check {{ timeout.check }}s
+ timeout connect {{ timeout.connect }}s
+ timeout client {{ timeout.client }}s
+ timeout server {{ timeout.server }}s
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
@@ -49,9 +50,29 @@ defaults
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
+# Default ACME backend
+backend buildin_acme_certbot
+ server localhost 127.0.0.1:{{ get_default_port('certbot_haproxy') }}
+
# Frontend
{% if service is vyos_defined %}
{% for front, front_config in service.items() %}
+{% if front_config.redirect_http_to_https is vyos_defined %}
+{% set certbot_backend_name = 'certbot_' ~ front ~ '_backend' %}
+frontend {{ front }}-http
+ mode http
+{% if front_config.listen_address is vyos_defined %}
+{% for address, server_config in front_config.listen_address.items() %}
+ bind {{ address | bracketize_ipv6 }}:80 {{ 'accept-proxy' if server_config.accept_proxy is vyos_defined }}
+{% endfor %}
+{% else %}
+ bind [::]:80 v4v6
+{% endif %}
+ acl acme_acl path_beg /.well-known/acme-challenge/
+ use_backend buildin_acme_certbot if acme_acl
+ redirect scheme https code 301 if !acme_acl
+{% endif %}
+
frontend {{ front }}
{% set ssl_front = [] %}
{% if front_config.ssl.certificate is vyos_defined and front_config.ssl.certificate is iterable %}
@@ -61,15 +82,12 @@ frontend {{ front }}
{% endif %}
{% set ssl_directive = 'ssl' if ssl_front else '' %}
{% if front_config.listen_address is vyos_defined %}
-{% for address in front_config.listen_address %}
- bind {{ address | bracketize_ipv6 }}:{{ front_config.port }} {{ ssl_directive }} {{ ssl_front | join(' ') }}
+{% for address, server_config in front_config.listen_address.items() %}
+ bind {{ address | bracketize_ipv6 }}:{{ front_config.port }} {{ ssl_directive }} {{ ssl_front | join(' ') }} {{ 'accept-proxy' if server_config.accept_proxy is vyos_defined }}
{% endfor %}
{% else %}
bind [::]:{{ front_config.port }} v4v6 {{ ssl_directive }} {{ ssl_front | join(' ') }}
{% endif %}
-{% if front_config.redirect_http_to_https is vyos_defined %}
- http-request redirect scheme https unless { ssl_fc }
-{% endif %}
{% if front_config.logging is vyos_defined %}
{% for facility, facility_config in front_config.logging.facility.items() %}
log /dev/log {{ facility }} {{ facility_config.level }}
@@ -93,17 +111,26 @@ frontend {{ front }}
http-response set-header {{ header }} '{{ header_config['value'] }}'
{% endfor %}
{% endif %}
+{% if front_config.http_compression is vyos_defined %}
+ filter compression
+ compression algo {{ front_config.http_compression.algorithm }}
+ compression type {{ front_config.http_compression.mime_type | join(' ') }}
+{% endif %}
{% if front_config.rule is vyos_defined %}
{% for rule, rule_config in front_config.rule.items() %}
# rule {{ rule }}
{% if rule_config.domain_name is vyos_defined %}
{% set rule_options = 'hdr(host)' %}
+{% set domain_prefix = '' %}
{% if rule_config.ssl is vyos_defined %}
{% set ssl_rule_translate = {'req-ssl-sni': 'req_ssl_sni', 'ssl-fc-sni': 'ssl_fc_sni', 'ssl-fc-sni-end': 'ssl_fc_sni_end'} %}
{% set rule_options = ssl_rule_translate[rule_config.ssl] %}
{% endif %}
+{% if rule_config.wildcard_domain is vyos_defined %}
+{% set domain_prefix = '-m end .' %}
+{% endif %}
{% for domain in rule_config.domain_name %}
- acl {{ rule }} {{ rule_options }} -i {{ domain }}
+ acl {{ rule }} {{ rule_options }} -i {{ domain_prefix }}{{ domain }}
{% endfor %}
{% endif %}
{# path url #}
@@ -129,6 +156,11 @@ frontend {{ front }}
default_backend {{ backend }}
{% endfor %}
{% endif %}
+{% if front_config.timeout is vyos_defined %}
+{% if front_config.timeout.client is vyos_defined %}
+ timeout client {{ front_config.timeout.client }}s
+{% endif %}
+{% endif %}
{% endfor %}
{% endif %}
@@ -189,12 +221,16 @@ backend {{ back }}
{% for rule, rule_config in back_config.rule.items() %}
{% if rule_config.domain_name is vyos_defined and rule_config.set.server is vyos_defined %}
{% set rule_options = 'hdr(host)' %}
+{% set domain_prefix = '' %}
{% if rule_config.ssl is vyos_defined %}
{% set ssl_rule_translate = {'req-ssl-sni': 'req_ssl_sni', 'ssl-fc-sni': 'ssl_fc_sni', 'ssl-fc-sni-end': 'ssl_fc_sni_end'} %}
{% set rule_options = ssl_rule_translate[rule_config.ssl] %}
{% endif %}
+{% if rule_config.wildcard_domain is vyos_defined %}
+{% set domain_prefix = '-m end .' %}
+{% endif %}
{% for domain in rule_config.domain_name %}
- acl {{ rule }} {{ rule_options }} -i {{ domain }}
+ acl {{ rule }} {{ rule_options }} -i {{ domain_prefix }}{{ domain }}
{% endfor %}
use-server {{ rule_config.set.server }} if {{ rule }}
{% endif %}
@@ -214,7 +250,30 @@ backend {{ back }}
{% if back_config.server is vyos_defined %}
{% set ssl_back = 'ssl ca-file /run/haproxy/' ~ back_config.ssl.ca_certificate ~ '.pem' if back_config.ssl.ca_certificate is vyos_defined else ('ssl verify none' if back_config.ssl.no_verify is vyos_defined else '') %}
{% for server, server_config in back_config.server.items() %}
- server {{ server }} {{ server_config.address }}:{{ server_config.port }}{{ ' check' if server_config.check is vyos_defined }}{{ ' backup' if server_config.backup is vyos_defined }}{{ ' send-proxy' if server_config.send_proxy is vyos_defined }}{{ ' send-proxy-v2' if server_config.send_proxy_v2 is vyos_defined }} {{ ssl_back }}
+{% set address = server_config.address %}
+{% set port = server_config.port %}
+{# Build optional flags #}
+{% set flags = [] %}
+{% if server_config.check is vyos_defined %}
+{% set _ = flags.append('check') %}
+{# Build nested 'check port' flag like this: '... check port 8080' #}
+{% if server_config.check.port is vyos_defined %}
+{% set _ = flags.extend(['port', server_config.check.port]) %}
+{% endif %}
+{% endif %}
+{% if server_config.backup is vyos_defined %}
+{% set _ = flags.append('backup') %}
+{% endif %}
+{% if server_config.send_proxy is vyos_defined %}
+{% set _ = flags.append('send-proxy') %}
+{% endif %}
+{% if server_config.send_proxy_v2 is vyos_defined %}
+{% set _ = flags.append('send-proxy-v2') %}
+{% endif %}
+{% if ssl_back %}
+{% set _ = flags.append(ssl_back) %}
+{% endif %}
+ server {{ server }} {{ address }}:{{ port }} {{ flags | select | join(' ') }}
{% endfor %}
{% endif %}
{% if back_config.timeout.check is vyos_defined %}
@@ -226,6 +285,5 @@ backend {{ back }}
{% if back_config.timeout.server is vyos_defined %}
timeout server {{ back_config.timeout.server }}s
{% endif %}
-
{% endfor %}
{% endif %}
diff --git a/data/templates/load-balancing/nftables-wlb.j2 b/data/templates/load-balancing/nftables-wlb.j2
new file mode 100644
index 000000000..6d71676c4
--- /dev/null
+++ b/data/templates/load-balancing/nftables-wlb.j2
@@ -0,0 +1,68 @@
+#!/usr/sbin/nft -f
+
+{% import 'firewall/nftables-defines.j2' as group_tmpl %}
+
+{% if first_install is not vyos_defined %}
+delete table ip vyos_wanloadbalance
+{% endif %}
+table ip vyos_wanloadbalance {
+ chain wlb_nat_postrouting {
+ type nat hook postrouting priority srcnat - 1; policy accept;
+{% for ifname, health_conf in interface_health.items() if health_state[ifname].if_addr %}
+{% if disable_source_nat is not vyos_defined %}
+{% set state = health_state[ifname] %}
+ ct mark {{ state.mark }} oifname {{ ifname }} counter snat to {{ state.if_addr }}
+{% endif %}
+{% endfor %}
+ }
+
+ chain wlb_mangle_prerouting {
+ type filter hook prerouting priority mangle; policy accept;
+{% for ifname, health_conf in interface_health.items() %}
+{% set state = health_state[ifname] %}
+{% if sticky_connections is vyos_defined %}
+ iifname "{{ ifname }}" ct state new ct mark set {{ state.mark }}
+{% endif %}
+{% endfor %}
+{% if rule is vyos_defined %}
+{% for rule_id, rule_conf in rule.items() %}
+{% if rule_conf.exclude is vyos_defined %}
+ {{ rule_conf | wlb_nft_rule(rule_id, exclude=True, action='return') }}
+{% else %}
+{% set limit = rule_conf.limit is vyos_defined %}
+ {{ rule_conf | wlb_nft_rule(rule_id, limit=limit, weight=True, health_state=health_state) }}
+ {{ rule_conf | wlb_nft_rule(rule_id, restore_mark=True) }}
+{% endif %}
+{% endfor %}
+{% endif %}
+ }
+
+ chain wlb_mangle_output {
+ type filter hook output priority -150; policy accept;
+{% if enable_local_traffic is vyos_defined %}
+ meta mark != 0x0 counter return
+ meta l4proto icmp counter return
+ ip saddr 127.0.0.0/8 ip daddr 127.0.0.0/8 counter return
+{% if rule is vyos_defined %}
+{% for rule_id, rule_conf in rule.items() %}
+{% if rule_conf.exclude is vyos_defined %}
+ {{ rule_conf | wlb_nft_rule(rule_id, local=True, exclude=True, action='return') }}
+{% else %}
+{% set limit = rule_conf.limit is vyos_defined %}
+ {{ rule_conf | wlb_nft_rule(rule_id, local=True, limit=limit, weight=True, health_state=health_state) }}
+ {{ rule_conf | wlb_nft_rule(rule_id, local=True, restore_mark=True) }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% endif %}
+ }
+
+{% for ifname, health_conf in interface_health.items() %}
+{% set state = health_state[ifname] %}
+ chain wlb_mangle_isp_{{ ifname }} {
+ meta mark set {{ state.mark }} ct mark set {{ state.mark }} counter accept
+ }
+{% endfor %}
+
+{{ group_tmpl.groups(firewall_group, False, True) }}
+}
diff --git a/data/templates/load-balancing/wlb.conf.j2 b/data/templates/load-balancing/wlb.conf.j2
deleted file mode 100644
index 7f04d797e..000000000
--- a/data/templates/load-balancing/wlb.conf.j2
+++ /dev/null
@@ -1,134 +0,0 @@
-### Autogenerated by load-balancing_wan.py ###
-
-{% if disable_source_nat is vyos_defined %}
-disable-source-nat
-{% endif %}
-{% if enable_local_traffic is vyos_defined %}
-enable-local-traffic
-{% endif %}
-{% if sticky_connections is vyos_defined %}
-sticky-connections inbound
-{% endif %}
-{% if flush_connections is vyos_defined %}
-flush-conntrack
-{% endif %}
-{% if hook is vyos_defined %}
-hook "{{ hook }}"
-{% endif %}
-{% if interface_health is vyos_defined %}
-health {
-{% for interface, interface_config in interface_health.items() %}
- interface {{ interface }} {
-{% if interface_config.failure_count is vyos_defined %}
- failure-ct {{ interface_config.failure_count }}
-{% endif %}
-{% if interface_config.success_count is vyos_defined %}
- success-ct {{ interface_config.success_count }}
-{% endif %}
-{% if interface_config.nexthop is vyos_defined %}
- nexthop {{ interface_config.nexthop }}
-{% endif %}
-{% if interface_config.test is vyos_defined %}
-{% for test_rule, test_config in interface_config.test.items() %}
- rule {{ test_rule }} {
-{% if test_config.type is vyos_defined %}
-{% set type_translate = {'ping': 'ping', 'ttl': 'udp', 'user-defined': 'user-defined'} %}
- type {{ type_translate[test_config.type] }} {
-{% if test_config.ttl_limit is vyos_defined and test_config.type == 'ttl' %}
- ttl {{ test_config.ttl_limit }}
-{% endif %}
-{% if test_config.test_script is vyos_defined and test_config.type == 'user-defined' %}
- test-script {{ test_config.test_script }}
-{% endif %}
-{% if test_config.target is vyos_defined %}
- target {{ test_config.target }}
-{% endif %}
- resp-time {{ test_config.resp_time | int * 1000 }}
- }
-{% endif %}
- }
-{% endfor %}
-{% endif %}
- }
-{% endfor %}
-}
-{% endif %}
-
-{% if rule is vyos_defined %}
-{% for rule, rule_config in rule.items() %}
-rule {{ rule }} {
-{% if rule_config.exclude is vyos_defined %}
- exclude
-{% endif %}
-{% if rule_config.failover is vyos_defined %}
- failover
-{% endif %}
-{% if rule_config.limit is vyos_defined %}
- limit {
-{% if rule_config.limit.burst is vyos_defined %}
- burst {{ rule_config.limit.burst }}
-{% endif %}
-{% if rule_config.limit.rate is vyos_defined %}
- rate {{ rule_config.limit.rate }}
-{% endif %}
-{% if rule_config.limit.period is vyos_defined %}
- period {{ rule_config.limit.period }}
-{% endif %}
-{% if rule_config.limit.threshold is vyos_defined %}
- thresh {{ rule_config.limit.threshold }}
-{% endif %}
- }
-{% endif %}
-{% if rule_config.per_packet_balancing is vyos_defined %}
- per-packet-balancing
-{% endif %}
-{% if rule_config.protocol is vyos_defined %}
- protocol {{ rule_config.protocol }}
-{% endif %}
-{% if rule_config.destination is vyos_defined %}
- destination {
-{% if rule_config.destination.address is vyos_defined %}
- address "{{ rule_config.destination.address }}"
-{% endif %}
-{% if rule_config.destination.port is vyos_defined %}
-{% if '-' in rule_config.destination.port %}
- port-ipt "-m multiport --dports {{ rule_config.destination.port | replace('-', ':') }}"
-{% elif ',' in rule_config.destination.port %}
- port-ipt "-m multiport --dports {{ rule_config.destination.port }}"
-{% else %}
- port-ipt " --dport {{ rule_config.destination.port }}"
-{% endif %}
-{% endif %}
- }
-{% endif %}
-{% if rule_config.source is vyos_defined %}
- source {
-{% if rule_config.source.address is vyos_defined %}
- address "{{ rule_config.source.address }}"
-{% endif %}
-{% if rule_config.source.port is vyos_defined %}
-{% if '-' in rule_config.source.port %}
- port-ipt "-m multiport --sports {{ rule_config.source.port | replace('-', ':') }}"
-{% elif ',' in rule_config.destination.port %}
- port-ipt "-m multiport --sports {{ rule_config.source.port }}"
-{% else %}
- port.ipt " --sport {{ rule_config.source.port }}"
-{% endif %}
-{% endif %}
- }
-{% endif %}
-{% if rule_config.inbound_interface is vyos_defined %}
- inbound-interface {{ rule_config.inbound_interface }}
-{% endif %}
-{% if rule_config.interface is vyos_defined %}
-{% for interface, interface_config in rule_config.interface.items() %}
- interface {{ interface }} {
-{% if interface_config.weight is vyos_defined %}
- weight {{ interface_config.weight }}
-{% endif %}
- }
-{% endfor %}
-{% endif %}
-}
-{% endfor %}
-{% endif %}
diff --git a/data/templates/login/authorized_keys.j2 b/data/templates/login/authorized_keys.j2
index 695b66abe..5b15f066a 100644
--- a/data/templates/login/authorized_keys.j2
+++ b/data/templates/login/authorized_keys.j2
@@ -1,5 +1,4 @@
### Automatically generated by system_login.py ###
-
{% if authentication.public_keys is vyos_defined %}
{% for key, key_options in authentication.public_keys.items() %}
{# The whitespace after options is wisely chosen #}
diff --git a/data/templates/login/authorized_principals.j2 b/data/templates/login/authorized_principals.j2
new file mode 100644
index 000000000..16525e808
--- /dev/null
+++ b/data/templates/login/authorized_principals.j2
@@ -0,0 +1,4 @@
+### Automatically generated by system_login.py ###
+{% if authentication.principal is vyos_defined %}
+{{ '\n'.join(authentication.principal) }}
+{% endif %}
diff --git a/data/templates/login/motd_user_dsa_warning.j2 b/data/templates/login/motd_user_dsa_warning.j2
new file mode 100644
index 000000000..f8164b184
--- /dev/null
+++ b/data/templates/login/motd_user_dsa_warning.j2
@@ -0,0 +1,18 @@
+{% if user is vyos_defined %}
+{% set ns = namespace (gen_header = True) %}
+{% for user, user_config in user.items() %}
+{% if user_config.authentication.public_keys is vyos_defined %}
+{% for key, key_options in user_config.authentication.public_keys.items() %}
+{% if key_options.type is vyos_defined('ssh-dss') %}
+{% if ns.gen_header %}
+{% set ns.gen_header = False %}
+---
+{{ ssh_dsa_deprecation_warning | wordwrap(72) }}
+
+{% endif %}
+User "{{ user }}" with deprecated public-key named: {{ key }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% endfor %}
+{% endif %}
diff --git a/data/templates/login/motd_vyos_nonproduction.j2 b/data/templates/login/motd_vyos_nonproduction.j2
new file mode 100644
index 000000000..4b81acc5b
--- /dev/null
+++ b/data/templates/login/motd_vyos_nonproduction.j2
@@ -0,0 +1,5 @@
+
+---
+WARNING: This VyOS system is not a stable long-term support version and
+ is not intended for production use.
+
diff --git a/data/templates/login/pam_radius_auth.conf.j2 b/data/templates/login/pam_radius_auth.conf.j2
index 75437ca71..f9b8d5e87 100644
--- a/data/templates/login/pam_radius_auth.conf.j2
+++ b/data/templates/login/pam_radius_auth.conf.j2
@@ -9,7 +9,7 @@
{% if address | is_ipv4 %}
{% set source_address.ipv4 = address %}
{% elif address | is_ipv6 %}
-{% set source_address.ipv6 = "[" + address + "]" %}
+{% set source_address.ipv6 = address %}
{% endif %}
{% endfor %}
{% endif %}
@@ -21,7 +21,7 @@
{% if server | is_ipv4 %}
{{ server }}:{{ options.port }} {{ "%-25s" | format(options.key) }} {{ "%-10s" | format(options.timeout) }} {{ source_address.ipv4 if source_address.ipv4 is vyos_defined }}
{% else %}
-[{{ server }}]:{{ options.port }} {{ "%-25s" | format(options.key) }} {{ "%-10s" | format(options.timeout) }} {{ source_address.ipv6 if source_address.ipv6 is vyos_defined }}
+{{ server | bracketize_ipv6 }}:{{ options.port }} {{ "%-25s" | format(options.key) }} {{ "%-10s" | format(options.timeout) }} {{ source_address.ipv6 if source_address.ipv6 is vyos_defined }}
{% endif %}
{% endfor %}
{% endif %}
diff --git a/data/templates/login/tacplus_nss.conf.j2 b/data/templates/login/tacplus_nss.conf.j2
index 2a30b1710..1c5402233 100644
--- a/data/templates/login/tacplus_nss.conf.j2
+++ b/data/templates/login/tacplus_nss.conf.j2
@@ -21,7 +21,7 @@
# Cumulus Linux ships with it set to 1001, so we never lookup our standard
# local users, including the cumulus uid of 1000. Should not be greater
# than the local tacacs{0..15} uids
-min_uid=900
+min_uid={{ tacacs_min_uid }}
# This is a comma separated list of usernames that are never sent to
# a tacacs server, they cause an early not found return.
@@ -30,7 +30,7 @@ min_uid=900
# that during pathname completion, bash can do an NSS lookup on "*"
# To avoid server round trip delays, or worse, unreachable server delays
# on filename completion, we include "*" in the exclusion list.
-exclude_users=root,telegraf,radvd,strongswan,tftp,conservr,frr,ocserv,pdns,_chrony,_lldpd,sshd,openvpn,radius_user,radius_priv_user,*{{ ',' + user | join(',') if user is vyos_defined }}
+exclude_users=*{{ ',' + exclude_users | join(',') if exclude_users is vyos_defined }}
# The include keyword allows centralizing the tacacs+ server information
# including the IP address and shared secret
@@ -71,4 +71,3 @@ source_ip={{ tacacs.source_address }}
# as in tacplus_servers, since tacplus_servers should not be readable
# by users other than root.
timeout={{ tacacs.timeout }}
-
diff --git a/data/templates/login/tacplus_servers.j2 b/data/templates/login/tacplus_servers.j2
index 23e8e495e..c38ddc593 100644
--- a/data/templates/login/tacplus_servers.j2
+++ b/data/templates/login/tacplus_servers.j2
@@ -41,7 +41,7 @@ vrf={{ tacacs.vrf }}
{% if tacacs.source_address is vyos_defined %}
# Sets the IPv4 address used as the source IP address when communicating with
# the TACACS+ server. IPv6 addresses are not supported, nor are hostnames.
-# The address must work when passsed to the bind() system call, that is, it must
+# The address must work when passed to the bind() system call, that is, it must
# be valid for the interface being used.
source_ip={{ tacacs.source_address }}
{% endif %}
diff --git a/data/templates/logs/logrotate/vyos-rsyslog.j2 b/data/templates/logs/logrotate/vyos-rsyslog.j2
index f2e4d2ab2..23e5810cd 100644
--- a/data/templates/logs/logrotate/vyos-rsyslog.j2
+++ b/data/templates/logs/logrotate/vyos-rsyslog.j2
@@ -1,3 +1,4 @@
+### Autogenerated by system_logs.py ###
/var/log/messages {
create
missingok
@@ -10,4 +11,3 @@
/usr/lib/rsyslog/rsyslog-rotate
endscript
}
-
diff --git a/data/templates/mdns-repeater/avahi-daemon.conf.j2 b/data/templates/mdns-repeater/avahi-daemon.conf.j2
index cc6495817..a5031945c 100644
--- a/data/templates/mdns-repeater/avahi-daemon.conf.j2
+++ b/data/templates/mdns-repeater/avahi-daemon.conf.j2
@@ -6,6 +6,9 @@ allow-interfaces={{ interface | join(', ') }}
{% if browse_domain is vyos_defined and browse_domain | length %}
browse-domains={{ browse_domain | join(', ') }}
{% endif %}
+{% if cache_entries is vyos_defined %}
+cache-entries-max={{ cache_entries }}
+{% endif %}
disallow-other-stacks=no
[wide-area]
diff --git a/data/templates/ndppd/ndppd.conf.j2 b/data/templates/ndppd/ndppd.conf.j2
index 6369dbdeb..fabe7feb8 100644
--- a/data/templates/ndppd/ndppd.conf.j2
+++ b/data/templates/ndppd/ndppd.conf.j2
@@ -10,7 +10,7 @@ route-ttl {{ route_refresh }}
proxy {{ iface }} {
# Turn on or off the router flag for Neighbor Advertisements
router {{ 'yes' if iface_config.enable_router_bit is vyos_defined else 'no' }}
- # Control how long to wait for a Neighbor Advertisment message before invalidating the entry (milliseconds)
+ # Control how long to wait for a Neighbor Advertisement message before invalidating the entry (milliseconds)
timeout {{ iface_config.timeout }}
# Control how long a valid or invalid entry remains in the cache (milliseconds)
ttl {{ iface_config.ttl }}
diff --git a/data/templates/nhrp/nftables.conf.j2 b/data/templates/nhrp/nftables.conf.j2
deleted file mode 100644
index a0d1f6d4c..000000000
--- a/data/templates/nhrp/nftables.conf.j2
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/sbin/nft -f
-
-{% if first_install is not vyos_defined %}
-delete table ip vyos_nhrp_filter
-{% endif %}
-table ip vyos_nhrp_filter {
- chain VYOS_NHRP_OUTPUT {
- type filter hook output priority 10; policy accept;
-{% if tunnel is vyos_defined %}
-{% for tun, tunnel_conf in tunnel.items() %}
-{% if if_tunnel[tun].source_address is vyos_defined %}
- ip protocol gre ip saddr {{ if_tunnel[tun].source_address }} ip daddr 224.0.0.0/4 counter drop comment "VYOS_NHRP_{{ tun }}"
-{% endif %}
-{% endfor %}
-{% endif %}
- }
-}
diff --git a/data/templates/nhrp/opennhrp.conf.j2 b/data/templates/nhrp/opennhrp.conf.j2
deleted file mode 100644
index c040a8f14..000000000
--- a/data/templates/nhrp/opennhrp.conf.j2
+++ /dev/null
@@ -1,42 +0,0 @@
-{# j2lint: disable=jinja-variable-format #}
-# Created by VyOS - manual changes will be overwritten
-
-{% if tunnel is vyos_defined %}
-{% for name, tunnel_conf in tunnel.items() %}
-{% set type = 'spoke' if tunnel_conf.map is vyos_defined or tunnel_conf.dynamic_map is vyos_defined else 'hub' %}
-{% set profile_name = profile_map[name] if profile_map is vyos_defined and name in profile_map else '' %}
-interface {{ name }} #{{ type }} {{ profile_name }}
-{% if tunnel_conf.map is vyos_defined %}
-{% for map, map_conf in tunnel_conf.map.items() %}
-{% set cisco = ' cisco' if map_conf.cisco is vyos_defined else '' %}
-{% set register = ' register' if map_conf.register is vyos_defined else '' %}
- map {{ map }} {{ map_conf.nbma_address }}{{ register }}{{ cisco }}
-{% endfor %}
-{% endif %}
-{% if tunnel_conf.dynamic_map is vyos_defined %}
-{% for map, map_conf in tunnel_conf.dynamic_map.items() %}
- dynamic-map {{ map }} {{ map_conf.nbma_domain_name }}
-{% endfor %}
-{% endif %}
-{% if tunnel_conf.cisco_authentication is vyos_defined %}
- cisco-authentication {{ tunnel_conf.cisco_authentication }}
-{% endif %}
-{% if tunnel_conf.holding_time is vyos_defined %}
- holding-time {{ tunnel_conf.holding_time }}
-{% endif %}
-{% if tunnel_conf.multicast is vyos_defined %}
- multicast {{ tunnel_conf.multicast }}
-{% endif %}
-{% for key in ['non_caching', 'redirect', 'shortcut', 'shortcut_destination'] %}
-{% if key in tunnel_conf %}
- {{ key | replace("_", "-") }}
-{% endif %}
-{% endfor %}
-{% if tunnel_conf.shortcut_target is vyos_defined %}
-{% for target, shortcut_conf in tunnel_conf.shortcut_target.items() %}
- shortcut-target {{ target }}{{ ' holding-time ' + shortcut_conf.holding_time if shortcut_conf.holding_time is vyos_defined }}
-{% endfor %}
-{% endif %}
-
-{% endfor %}
-{% endif %}
diff --git a/data/templates/ocserv/ocserv_config.j2 b/data/templates/ocserv/ocserv_config.j2
index 81f777031..e8549b1bb 100644
--- a/data/templates/ocserv/ocserv_config.j2
+++ b/data/templates/ocserv/ocserv_config.j2
@@ -30,6 +30,15 @@ auth = "plain[otp=/run/ocserv/users.oath]"
{% else %}
auth = "plain[/run/ocserv/ocpasswd]"
{% endif %}
+{% elif "certificate" in authentication.mode %}
+auth = "certificate"
+{% if authentication.mode.certificate.user_identifier_field == "cn" %}
+cert-user-oid = 2.5.4.3
+{% elif authentication.mode.certificate.user_identifier_field == "uid" %}
+cert-user-oid = 0.9.2342.19200300.100.1.1
+{% else %}
+cert-user-oid = {{ authentication.mode.certificate.user_identifier_field }}
+{% endif %}
{% else %}
auth = "plain[/run/ocserv/ocpasswd]"
{% endif %}
@@ -41,6 +50,14 @@ default-user-config = {{ authentication.identity_based_config.default_config }}
{% endif %}
{% endif %}
+{% if script.connect is vyos_defined %}
+connect-script = {{ script.connect }}
+{% endif %}
+
+{% if script.disconnect is vyos_defined %}
+disconnect-script = {{ script.disconnect }}
+{% endif %}
+
{% if ssl.certificate is vyos_defined %}
server-cert = /run/ocserv/cert.pem
server-key = /run/ocserv/cert.key
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/data/templates/openvpn/server.conf.j2 b/data/templates/openvpn/server.conf.j2
index be811f45e..19c8e226c 100644
--- a/data/templates/openvpn/server.conf.j2
+++ b/data/templates/openvpn/server.conf.j2
@@ -217,6 +217,9 @@ cipher {{ encryption.cipher | openvpn_cipher }}
{% if encryption.data_ciphers is vyos_defined %}
data-ciphers {{ encryption.data_ciphers | openvpn_data_ciphers }}
{% endif %}
+{% if encryption.data_ciphers_fallback is vyos_defined %}
+data-ciphers-fallback {{ encryption.data_ciphers_fallback | openvpn_data_ciphers_fallback }}
+{% endif %}
{% endif %}
providers default
diff --git a/data/templates/pmacct/override.conf.j2 b/data/templates/pmacct/override.conf.j2
deleted file mode 100644
index 44a100bb6..000000000
--- a/data/templates/pmacct/override.conf.j2
+++ /dev/null
@@ -1,17 +0,0 @@
-{% set vrf_command = 'ip vrf exec ' ~ vrf ~ ' ' if vrf is vyos_defined else '' %}
-[Unit]
-After=
-After=vyos-router.service
-ConditionPathExists=
-ConditionPathExists=/run/pmacct/uacctd.conf
-
-[Service]
-EnvironmentFile=
-ExecStart=
-ExecStart={{ vrf_command }}/usr/sbin/uacctd -f /run/pmacct/uacctd.conf
-ExecStop=/usr/libexec/vyos/system/uacctd_stop.py $MAINPID 60
-WorkingDirectory=
-WorkingDirectory=/run/pmacct
-Restart=always
-RestartSec=10
-KillMode=mixed
diff --git a/data/templates/pmacct/uacctd.conf.j2 b/data/templates/pmacct/uacctd.conf.j2
deleted file mode 100644
index aae0a0619..000000000
--- a/data/templates/pmacct/uacctd.conf.j2
+++ /dev/null
@@ -1,80 +0,0 @@
-# Genereated from VyOS configuration
-daemonize: true
-promisc: false
-syslog: daemon
-uacctd_group: 2
-uacctd_nl_size: 2097152
-snaplen: {{ packet_length }}
-aggregate: in_iface{{ ',out_iface' if enable_egress is vyos_defined }},src_mac,dst_mac,vlan,src_host,dst_host,src_port,dst_port,proto,tos,flows
-{% set pipe_size = buffer_size | int *1024 *1024 %}
-plugin_pipe_size: {{ pipe_size }}
-{# We need an integer division (//) without any remainder or fraction #}
-plugin_buffer_size: {{ pipe_size // 1000 }}
-{% if syslog_facility is vyos_defined %}
-syslog: {{ syslog_facility }}
-{% endif %}
-{% if disable_imt is not defined %}
-imt_path: /tmp/uacctd.pipe
-imt_mem_pools_number: 169
-{% endif %}
-
-{% set plugin = [] %}
-{% if netflow.server is vyos_defined %}
-{% for server in netflow.server %}
-{% set nf_server_key = 'nf_' ~ server | dot_colon_to_dash %}
-{% set _ = plugin.append('nfprobe['~ nf_server_key ~ ']') %}
-{% endfor %}
-{% endif %}
-{% if sflow.server is vyos_defined %}
-{% for server in sflow.server %}
-{% set sf_server_key = 'sf_' ~ server | dot_colon_to_dash %}
-{% set _ = plugin.append('sfprobe[' ~ sf_server_key ~ ']') %}
-{% endfor %}
-{% endif %}
-{% if disable_imt is not defined %}
-{% set _ = plugin.append('memory') %}
-{% endif %}
-plugins: {{ plugin | join(',') }}
-
-{% if netflow.server is vyos_defined %}
-# NetFlow servers
-{% for server, server_config in netflow.server.items() %}
-{# # prevent pmacct syntax error when using IPv6 flow collectors #}
-{% set nf_server_key = 'nf_' ~ server | dot_colon_to_dash %}
-nfprobe_receiver[{{ nf_server_key }}]: {{ server | bracketize_ipv6 }}:{{ server_config.port }}
-nfprobe_version[{{ nf_server_key }}]: {{ netflow.version }}
-{% if netflow.engine_id is vyos_defined %}
-nfprobe_engine[{{ nf_server_key }}]: {{ netflow.engine_id }}
-{% endif %}
-{% if netflow.max_flows is vyos_defined %}
-nfprobe_maxflows[{{ nf_server_key }}]: {{ netflow.max_flows }}
-{% endif %}
-{% if netflow.sampling_rate is vyos_defined %}
-sampling_rate[{{ nf_server_key }}]: {{ netflow.sampling_rate }}
-{% endif %}
-{% if netflow.source_address is vyos_defined %}
-nfprobe_source_ip[{{ nf_server_key }}]: {{ netflow.source_address | bracketize_ipv6 }}
-{% endif %}
-{% if netflow.timeout is vyos_defined %}
-nfprobe_timeouts[{{ nf_server_key }}]: expint={{ netflow.timeout.expiry_interval }}:general={{ netflow.timeout.flow_generic }}:icmp={{ netflow.timeout.icmp }}:maxlife={{ netflow.timeout.max_active_life }}:tcp.fin={{ netflow.timeout.tcp_fin }}:tcp={{ netflow.timeout.tcp_generic }}:tcp.rst={{ netflow.timeout.tcp_rst }}:udp={{ netflow.timeout.udp }}
-{% endif %}
-
-{% endfor %}
-{% endif %}
-
-{% if sflow.server is vyos_defined %}
-# sFlow servers
-{% for server, server_config in sflow.server.items() %}
-{# # prevent pmacct syntax error when using IPv6 flow collectors #}
-{% set sf_server_key = 'sf_' ~ server | dot_colon_to_dash %}
-sfprobe_receiver[{{ sf_server_key }}]: {{ server | bracketize_ipv6 }}:{{ server_config.port }}
-sfprobe_agentip[{{ sf_server_key }}]: {{ sflow.agent_address }}
-{% if sflow.sampling_rate is vyos_defined %}
-sampling_rate[{{ sf_server_key }}]: {{ sflow.sampling_rate }}
-{% endif %}
-{% if sflow.source_address is vyos_defined %}
-sfprobe_source_ip[{{ sf_server_key }}]: {{ sflow.source_address | bracketize_ipv6 }}
-{% endif %}
-
-{% endfor %}
-{% endif %}
diff --git a/data/templates/pppoe/peer.j2 b/data/templates/pppoe/peer.j2
index efe47f369..fc2c605f4 100644
--- a/data/templates/pppoe/peer.j2
+++ b/data/templates/pppoe/peer.j2
@@ -59,7 +59,7 @@ mru {{ mru }}
{{ "usepeerdns" if no_peer_dns is not vyos_defined }}
-{% if ipv6 is vyos_defined %}
+{% if ipv6 is vyos_defined or dhcpv6_options.pd is vyos_defined or (address is vyos_defined and 'dhcpv6' in address) %}
+ipv6 {{ 'ipv6cp-use-ipaddr' if ipv6.address.autoconf is vyos_defined }}
{% else %}
noipv6
diff --git a/data/templates/prometheus/blackbox_exporter.service.j2 b/data/templates/prometheus/blackbox_exporter.service.j2
new file mode 100644
index 000000000..0b846ab73
--- /dev/null
+++ b/data/templates/prometheus/blackbox_exporter.service.j2
@@ -0,0 +1,21 @@
+{% set vrf_command = 'ip vrf exec ' ~ vrf ~ ' runuser -u node_exporter -- ' if vrf is vyos_defined else '' %}
+[Unit]
+Description=Blackbox Exporter
+Documentation=https://github.com/prometheus/blackbox_exporter
+After=network.target
+
+[Service]
+{% if vrf is not vyos_defined %}
+User=node_exporter
+{% endif %}
+ExecStart={{ vrf_command }}/usr/sbin/blackbox_exporter \
+{% if listen_address is vyos_defined %}
+{% for address in listen_address %}
+ --web.listen-address={{ address | bracketize_ipv6 }}:{{ port }} \
+{% endfor %}
+{% else %}
+ --web.listen-address=:{{ port }} \
+{% endif %}
+ --config.file=/run/blackbox_exporter/config.yml
+[Install]
+WantedBy=multi-user.target
diff --git a/data/templates/prometheus/blackbox_exporter.yml.j2 b/data/templates/prometheus/blackbox_exporter.yml.j2
new file mode 100644
index 000000000..ba2eecd77
--- /dev/null
+++ b/data/templates/prometheus/blackbox_exporter.yml.j2
@@ -0,0 +1,23 @@
+modules:
+{% if modules is defined and modules.dns is defined and modules.dns.name is defined %}
+{% for module_name, module_config in modules.dns.name.items() %}
+ {{ module_name }}:
+ prober: dns
+ timeout: {{ module_config.timeout }}s
+ dns:
+ query_name: "{{ module_config.query_name }}"
+ query_type: "{{ module_config.query_type }}"
+ preferred_ip_protocol: "{{ module_config.preferred_ip_protocol | replace('v', '') }}"
+ ip_protocol_fallback: {{ 'true' if module_config.ip_protocol_fallback is vyos_defined else 'false' }}
+{% endfor %}
+{% endif %}
+{% if modules is defined and modules.icmp is vyos_defined and modules.icmp.name is vyos_defined %}
+{% for module_name, module_config in modules.icmp.name.items() %}
+ {{ module_name }}:
+ prober: icmp
+ timeout: {{ module_config.timeout }}s
+ icmp:
+ preferred_ip_protocol: "{{ module_config.preferred_ip_protocol | replace('v', '') }}"
+ ip_protocol_fallback: {{ 'true' if module_config.ip_protocol_fallback is vyos_defined else 'false' }}
+{% endfor %}
+{% endif %} \ No newline at end of file
diff --git a/data/templates/prometheus/frr_exporter.service.j2 b/data/templates/prometheus/frr_exporter.service.j2
new file mode 100644
index 000000000..f80bad2cd
--- /dev/null
+++ b/data/templates/prometheus/frr_exporter.service.j2
@@ -0,0 +1,21 @@
+{% set vrf_command = 'ip vrf exec ' ~ vrf ~ ' runuser -u frr -- ' if vrf is vyos_defined else '' %}
+[Unit]
+Description=FRR Exporter
+Documentation=https://github.com/tynany/frr_exporter
+After=network.target
+
+[Service]
+{% if vrf is not vyos_defined %}
+User=frr
+{% endif %}
+ExecStart={{ vrf_command }}/usr/sbin/frr_exporter \
+ --collector.bgp6 \
+{% if listen_address is vyos_defined %}
+{% for address in listen_address %}
+ --web.listen-address={{ address | bracketize_ipv6 }}:{{ port }}
+{% endfor %}
+{% else %}
+ --web.listen-address=:{{ port }}
+{% endif %}
+[Install]
+WantedBy=multi-user.target
diff --git a/data/templates/prometheus/node_exporter.service.j2 b/data/templates/prometheus/node_exporter.service.j2
new file mode 100644
index 000000000..ef2f709b6
--- /dev/null
+++ b/data/templates/prometheus/node_exporter.service.j2
@@ -0,0 +1,26 @@
+{% 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 collectors is vyos_defined %}
+{% if collectors.textfile is vyos_defined %}
+ --collector.textfile.directory=/run/node_exporter/collector \
+{% endif %}
+{% endif %}
+{% if listen_address is vyos_defined %}
+{% for address in listen_address %}
+ --web.listen-address={{ address | bracketize_ipv6 }}:{{ port }}
+{% endfor %}
+{% else %}
+ --web.listen-address=:{{ port }}
+{% endif %}
+
+[Install]
+WantedBy=multi-user.target
diff --git a/data/templates/protocols/systemd_vyos_failover_service.j2 b/data/templates/protocols/systemd_vyos_failover_service.j2
index e6501e0f5..59189b1b8 100644
--- a/data/templates/protocols/systemd_vyos_failover_service.j2
+++ b/data/templates/protocols/systemd_vyos_failover_service.j2
@@ -5,7 +5,7 @@ After=vyos-router.service
[Service]
Type=simple
Restart=always
-ExecStart=/usr/bin/python3 /usr/libexec/vyos/vyos-failover.py --config /run/vyos-failover.conf
+ExecStart=/usr/bin/python3 /usr/libexec/vyos/vyos-failover.py --config-dir {{ config_dir }}
[Install]
WantedBy=multi-user.target
diff --git a/data/templates/router-advert/radvd.conf.j2 b/data/templates/router-advert/radvd.conf.j2
index a83bd03ac..3da405688 100644
--- a/data/templates/router-advert/radvd.conf.j2
+++ b/data/templates/router-advert/radvd.conf.j2
@@ -4,6 +4,9 @@
{% for iface, iface_config in interface.items() %}
interface {{ iface }} {
IgnoreIfMissing on;
+{% if iface_config.captive_portal is vyos_defined %}
+ AdvCaptivePortalAPI "{{ iface_config.captive_portal }}";
+{% endif %}
{% if iface_config.default_preference is vyos_defined %}
AdvDefaultPreference {{ iface_config.default_preference }};
{% endif %}
@@ -57,6 +60,21 @@ interface {{ iface }} {
};
{% endfor %}
{% endif %}
+{% if iface_config.prefix is vyos_defined and "::/64" in iface_config.prefix %}
+{% if iface_config.auto_ignore is vyos_defined or iface_config.prefix | count > 1 %}
+ autoignoreprefixes {
+{% if iface_config.auto_ignore is vyos_defined %}
+{% for auto_ignore_prefix in (iface_config.auto_ignore + iface_config.prefix | list) | reject("eq", "::/64") | unique %}
+ {{ auto_ignore_prefix }};
+{% endfor %}
+{% else %}
+{% for auto_ignore_prefix in iface_config.prefix | reject("eq", "::/64") %}
+ {{ auto_ignore_prefix }};
+{% endfor %}
+{% endif %}
+ };
+{% endif %}
+{% endif %}
{% if iface_config.prefix is vyos_defined %}
{% for prefix, prefix_options in iface_config.prefix.items() %}
prefix {{ prefix }} {
@@ -66,6 +84,9 @@ interface {{ iface }} {
AdvPreferredLifetime {{ prefix_options.preferred_lifetime }};
DeprecatePrefix {{ 'on' if prefix_options.deprecate_prefix is vyos_defined else 'off' }};
DecrementLifetimes {{ 'on' if prefix_options.decrement_lifetime is vyos_defined else 'off' }};
+{% if prefix_options.base_interface is vyos_defined %}
+ Base6Interface {{ prefix_options.base_interface }};
+{% endif %}
};
{% endfor %}
{% endif %}
diff --git a/data/templates/rsyslog/logrotate.j2 b/data/templates/rsyslog/logrotate.j2
deleted file mode 100644
index b9689a1cf..000000000
--- a/data/templates/rsyslog/logrotate.j2
+++ /dev/null
@@ -1,21 +0,0 @@
-### Autogenerated by system_syslog.py ###
-/var/log/messages {
- missingok
- notifempty
- create
- rotate 5
- size=256k
-}
-
-{% if file is vyos_defined %}
-{% for file_name, file_options in file.items() %}
-/var/log/user/{{ file_name }} {
- missingok
- notifempty
- create
- rotate {{ file_options.archive.file }}
- size={{ file_options.archive.size | int // 1024 }}k
-}
-
-{% endfor %}
-{% endif %}
diff --git a/data/templates/rsyslog/override.conf.j2 b/data/templates/rsyslog/override.conf.j2
deleted file mode 100644
index 5f6a87edf..000000000
--- a/data/templates/rsyslog/override.conf.j2
+++ /dev/null
@@ -1,11 +0,0 @@
-{% set vrf_command = 'ip vrf exec ' ~ vrf ~ ' ' if vrf is vyos_defined else '' %}
-[Unit]
-StartLimitIntervalSec=0
-
-[Service]
-ExecStart=
-ExecStart={{ vrf_command }}/usr/sbin/rsyslogd -n -iNONE
-Restart=always
-RestartPreventExitStatus=
-RestartSec=10
-RuntimeDirectoryPreserve=yes
diff --git a/data/templates/rsyslog/rsyslog.conf.j2 b/data/templates/rsyslog/rsyslog.conf.j2
index effc2ea14..3eb6f258a 100644
--- a/data/templates/rsyslog/rsyslog.conf.j2
+++ b/data/templates/rsyslog/rsyslog.conf.j2
@@ -1,76 +1,162 @@
### Autogenerated by system_syslog.py ###
-{% if global.marker is vyos_defined %}
-$ModLoad immark
-{% if global.marker.interval is vyos_defined %}
-$MarkMessagePeriod {{ global.marker.interval }}
-{% endif %}
+#### MODULES ####
+# Load input modules for local logging and journald
+
+# Old-style log file format with low-precision timestamps
+# A modern-style logfile format with high-precision timestamps and timezone info
+# RSYSLOG_FileFormat
+module(load="builtin:omfile" Template="RSYSLOG_TraditionalFileFormat")
+module(load="imuxsock") # provides support for local system logging (collection from /dev/log unix socket)
+
+# Import logs from journald, which includes kernel log messages
+module(
+ load="imjournal"
+ StateFile="/var/spool/rsyslog/imjournal.state" # Persistent state file to track the journal cursor
+ Ratelimit.Interval="0" # Disable rate limiting (set to "0" for no limit)
+ RateLimit.Burst="0"
+)
+
+###########################
+#### GLOBAL DIRECTIVES ####
+###########################
+# Log specific programs to auth.log, then stop further processing
+if (
+ $programname == "CRON" or
+ $programname == "sudo" or
+ $programname == "su"
+) then {
+ action(type="omfile" file="/var/log/auth.log")
+ stop
+}
+
+global(workDirectory="/var/spool/rsyslog")
+
+###############
+#### RULES ####
+###############
+
+# Send emergency messages to all logged-in users
+*.emerg action(type="omusrmsg" users="*")
+
+{% if marker is vyos_defined and marker.disable is not vyos_defined %}
+# Load the immark module for periodic --MARK-- message capability
+module(load="immark" interval="{{ marker.interval }}")
{% endif %}
-{% if global.preserve_fqdn is vyos_defined %}
-$PreserveFQDN on
+{% if preserve_fqdn is vyos_defined %}
+# Preserve the fully qualified domain name (FQDN) in log messages
+global(preserveFQDN="on")
+{% if preserve_fqdn.host_name is vyos_defined and preserve_fqdn.domain_name is vyos_defined %}
+# Set the local hostname for log messages
+global(localHostname="{{ preserve_fqdn.host_name }}.{{ preserve_fqdn.domain_name }}")
+{% endif %}
{% endif %}
-# We always log to /var/log/messages
-$outchannel global,/var/log/messages,262144,/usr/sbin/logrotate {{ logrotate }}
-{% if global.facility is vyos_defined %}
-{% set tmp = [] %}
-{% for facility, facility_options in global.facility.items() %}
-{% set _ = tmp.append(facility.replace('all', '*') + '.' + facility_options.level.replace('all', '*')) %}
-{% endfor %}
-{{ tmp | join(';') }} :omfile:$global
-{% endif %}
+{# Build a prifilt selector list with "all" excluding any explicitly-set facilities #}
+{% macro prifilt_selectors(facility_map) %}
+{# pass 1: collect explicit facilities #}
+{% set selectors = [] %}
+{% set keys = facility_map.keys() | list | sort %}
+{% set specific = [] %}
+{% for facility in keys %}
+{% if facility != 'all' %}
+{% set _ = specific.append(facility) %}
+{% endif %}
+{% endfor %}
+{# pass 2: build selectors; add ;fac.none exclusions to wildcard #}
+{% for facility in keys %}
+{% set opts = facility_map[facility] %}
+{% set level = opts.level.replace('all', 'debug') %}
+{% if facility == 'all' %}
+{% set ns = namespace(sel="*." ~ level) %}
+{% for sf in specific %}
+{% set ns.sel = ns.sel ~ ";" ~ sf ~ ".none" %}
+{% endfor %}
+{% set sel = ns.sel %}
+{% else %}
+{% set sel = facility ~ "." ~ level %}
+{% endif %}
+{% set _ = selectors.append(sel) %}
+{% endfor %}
+{{ selectors | join(',') }}
+{% endmacro %}
-{% if file is vyos_defined %}
-# File based configuration section
-{% for file_name, file_options in file.items() %}
-{% set tmp = [] %}
-$outchannel {{ file_name }},/var/log/user/{{ file_name }},{{ file_options.archive.size }},/usr/sbin/logrotate {{ logrotate }}
-{% if file_options.facility is vyos_defined %}
-{% for facility, facility_options in file_options.facility.items() %}
-{% set _ = tmp.append(facility.replace('all', '*') + '.' + facility_options.level.replace('all', '*')) %}
-{% endfor %}
-{% endif %}
-{{ tmp | join(';') }} :omfile:${{ file }}
-{% endfor %}
+#### GLOBAL LOGGING ####
+{% if local.facility is vyos_defined %}
+if prifilt("{{ prifilt_selectors(local.facility) | trim }}") then {
+ action(
+ type="omfile"
+ file="/var/log/messages"
+ rotation.sizeLimit="{{ logrotate_size_limit }}" # maximum filesize before rotation
+ rotation.sizeLimitCommand="/usr/sbin/logrotate {{ logrotate }}"
+ )
+}
{% endif %}
+#### CONSOLE LOGGING ####
{% if console.facility is vyos_defined %}
-# Console logging
-{% set tmp = [] %}
-{% for facility, facility_options in console.facility.items() %}
-{% set _ = tmp.append(facility.replace('all', '*') + '.' + facility_options.level.replace('all', '*')) %}
-{% endfor %}
-{{ tmp | join(';') }} /dev/console
+if prifilt("{{ prifilt_selectors(console.facility) | trim }}") then {
+ action(type="omfile" file="/dev/console")
+}
{% endif %}
-{% if host is vyos_defined %}
-# Remote logging
-{% for host_name, host_options in host.items() %}
-{% set tmp = [] %}
-{% if host_options.facility is vyos_defined %}
-{% for facility, facility_options in host_options.facility.items() %}
-{% set _ = tmp.append(facility.replace('all', '*') + '.' + facility_options.level.replace('all', '*')) %}
-{% endfor %}
-{% endif %}
-{% if host_options.protocol is vyos_defined('tcp') %}
-{% if host_options.format.octet_counted is vyos_defined %}
-{{ tmp | join(';') }} @@{{ '(o)' if host_options.format.octet_counted is vyos_defined }}{{ host_name | bracketize_ipv6 }}:{{ host_options.port }}{{ ';RSYSLOG_SyslogProtocol23Format' if host_options.format.include_timezone is vyos_defined }}
+#### REMOTE LOGGING ####
+{% if remote is vyos_defined %}
+{% for remote_name, remote_options in remote.items() %}
+{% if remote_options.facility is vyos_defined %}
+{% set tls = remote_options.tls %}
+# Remote syslog to {{ remote_name }}
+if prifilt("{{ prifilt_selectors(remote_options.facility) | trim }}") then {
+ action(
+ type="omfwd"
+ # Remote syslog server where we send our logs to
+ target="{{ remote_name }}"
+ # Port on the remote syslog server
+ port="{{ remote_options.port }}"
+ protocol="{{ 'tcp' if tls is vyos_defined else remote_options.protocol }}"
+{% if remote_options.format.include_timezone is vyos_defined %}
+ template="RSYSLOG_SyslogProtocol23Format"
+{% endif %}
+ TCP_Framing="{{ 'octet-counted' if remote_options.format.octet_counted is vyos_defined else 'traditional' }}"
+{% if remote_options.source_address is vyos_defined %}
+ Address="{{ remote_options.source_address }}"
{% endif %}
-{% else %}
-{{ tmp | join(';') }} @{{ host_name | bracketize_ipv6 }}:{{ host_options.port }}{{ ';RSYSLOG_SyslogProtocol23Format' if host_options.format.include_timezone is vyos_defined }}
+{% if remote_options.vrf is vyos_defined %}
+ Device="{{ remote_options.vrf }}"
+{% endif %}
+{% if tls is vyos_defined %}
+{% set auth_mode = tls.auth_mode %}
+ # Specify the use of the OpenSSL TLS driver for this action
+ StreamDriver="ossl"
+ # Set mode to TLS-only connections (do not accept plain TCP)
+ StreamDriverMode="1"
+ # Select the authentication mode
+ StreamDriverAuthMode="{{ auth_mode if auth_mode == 'anon' else 'x509/' + auth_mode }}"
+{% if tls.permitted_peer is vyos_defined and auth_mode in ('fingerprint', 'name') %}
+{% set permitted_peers = tls.permitted_peer | map('trim') | select | join(',') %}
+{% if permitted_peers %}
+ # Only include permitted peers (list of allowed fingerprints or names)
+ StreamDriverPermittedPeers="{{ permitted_peers }}"
+{% endif %}
+{% endif %}
+{% if tls.ca_certificate_path is vyos_defined %}
+ # Include the path to the CA certificate file
+ StreamDriver.CAFile="{{ tls.ca_certificate_path }}"
+{% endif %}
+{% if tls.certificate_path is vyos_defined %}
+ # Include the path to the client's certificate
+ StreamDriver.CertFile="{{ tls.certificate_path }}"
+{% endif %}
+{% if tls.certificate_key_path is vyos_defined %}
+ # Include the path to the client's private key
+ StreamDriver.KeyFile="{{ tls.certificate_key_path }}"
+{% endif %}
+{% endif %}
+ )
+}
{% endif %}
{% endfor %}
{% endif %}
-{% if user is defined and user is not none %}
-# Log to user terminal
-{% for username, user_options in user.items() %}
-{% set tmp = [] %}
-{% if user_options.facility is vyos_defined %}
-{% for facility, facility_options in user_options.facility.items() %}
-{% set _ = tmp.append(facility.replace('all', '*') + '.' + facility_options.level.replace('all', '*')) %}
-{% endfor %}
-{% endif %}
-{{ tmp | join(';') }} :omusrmsg:{{ username }}
-{% endfor %}
-{% endif %}
+# Include all configuration files in /etc/rsyslog.d/
+include(file="/etc/rsyslog.d/*.conf")
diff --git a/data/templates/sflow/hsflowd.conf.j2 b/data/templates/sflow/hsflowd.conf.j2
index 5000956bd..2bc249176 100644
--- a/data/templates/sflow/hsflowd.conf.j2
+++ b/data/templates/sflow/hsflowd.conf.j2
@@ -1,4 +1,4 @@
-# Genereated by /usr/libexec/vyos/conf_mode/system_sflow.py
+# Generated by /usr/libexec/vyos/conf_mode/system_sflow.py
# Parameters http://sflow.net/host-sflow-linux-config.php
sflow {
@@ -25,8 +25,14 @@ sflow {
pcap { dev={{ iface }} }
{% endfor %}
{% endif %}
+{% if enable_egress is vyos_defined %}
+ psample { group=1 egress=on }
+{% endif %}
{% if drop_monitor_limit is vyos_defined %}
dropmon { limit={{ drop_monitor_limit }} start=on sw=on hw=off }
{% endif %}
dbus { }
+{% if vpp is vyos_defined %}
+ vpp { }
+{% endif %}
}
diff --git a/data/templates/snmp/etc.snmpd.conf.j2 b/data/templates/snmp/etc.snmpd.conf.j2
index 9d91192fc..978ea9b7e 100644
--- a/data/templates/snmp/etc.snmpd.conf.j2
+++ b/data/templates/snmp/etc.snmpd.conf.j2
@@ -164,6 +164,10 @@ access {{ group }} "" usm {{ group_config.seclevel }} exact {{ group_config.view
# trap-target
{% if v3.trap_target is vyos_defined %}
{% for trap, trap_config in v3.trap_target.items() %}
+{% set protocol = trap_config.protocol %}
+{% if trap | is_ipv6 %}
+{% set protocol = protocol ~ '6' %}
+{% endif %}
{% set options = '' %}
{% if trap_config.type == 'inform' %}
{% set options = options ~ ' -Ci' %}
@@ -175,14 +179,14 @@ access {{ group }} "" usm {{ group_config.seclevel }} exact {{ group_config.view
{% set options = options ~ ' -u ' ~ trap_config.user %}
{% endif %}
{% if trap_config.auth.plaintext_password is vyos_defined or trap_config.auth.encrypted_password is vyos_defined %}
-{% set options = options ~ ' -a ' ~ trap_config.auth.type %}
+{% set options = options ~ ' -a ' ~ trap_config.auth.type | upper %}
{% if trap_config.auth.plaintext_password is vyos_defined %}
{% set options = options ~ ' -A ' ~ trap_config.auth.plaintext_password %}
{% elif trap_config.auth.encrypted_password is vyos_defined %}
{% set options = options ~ ' -3m ' ~ trap_config.auth.encrypted_password %}
{% endif %}
{% if trap_config.privacy.plaintext_password is vyos_defined or trap_config.privacy.encrypted_password is vyos_defined %}
-{% set options = options ~ ' -x ' ~ trap_config.privacy.type %}
+{% set options = options ~ ' -x ' ~ trap_config.privacy.type | upper %}
{% if trap_config.privacy.plaintext_password is vyos_defined %}
{% set options = options ~ ' -X ' ~ trap_config.privacy.plaintext_password %}
{% elif trap_config.privacy.encrypted_password is vyos_defined %}
@@ -195,7 +199,7 @@ access {{ group }} "" usm {{ group_config.seclevel }} exact {{ group_config.view
{% else %}
{% set options = options ~ ' -l noAuthNoPriv' %}
{% endif %}
-trapsess -v 3 {{ options }} {{ trap }}:{{ trap_config.protocol }}:{{ trap_config.port }}
+trapsess -v 3 {{ options }} {{ protocol }}:{{ trap | bracketize_ipv6 }}:{{ trap_config.port }}
{% endfor %}
{% endif %}
diff --git a/data/templates/snmp/override.conf.j2 b/data/templates/snmp/override.conf.j2
index 42dc7a9d2..33b610fe3 100644
--- a/data/templates/snmp/override.conf.j2
+++ b/data/templates/snmp/override.conf.j2
@@ -8,5 +8,7 @@ Environment=
Environment="MIBDIRS=/usr/share/snmp/mibs:/usr/share/snmp/mibs/iana:/usr/share/snmp/mibs/ietf:/usr/share/vyos/mibs"
ExecStart=
ExecStart={{ vrf_command }}/usr/sbin/snmpd -LS0-5d -Lf /dev/null -u Debian-snmp -g Debian-snmp -f -p /run/snmpd.pid
+# Sync engineBoot value between snmpd.conf and engineboots.count when user restarts the service manually
+ExecStartPost=!/usr/bin/python3 /usr/libexec/vyos/system/sync-snmp-engine-boots.py
Restart=always
RestartSec=10
diff --git a/data/templates/snmp/var.snmpd.conf.j2 b/data/templates/snmp/var.snmpd.conf.j2
index afab88abc..29abaa81c 100644
--- a/data/templates/snmp/var.snmpd.conf.j2
+++ b/data/templates/snmp/var.snmpd.conf.j2
@@ -14,3 +14,5 @@ createUser {{ vyos_user }} MD5 "{{ vyos_user_pass }}" DES
oldEngineID 0x{{ v3.engineid }}
{% endif %}
{% endif %}
+
+engineBoots {{ engine_boots }}
diff --git a/data/templates/squid/squid.conf.j2 b/data/templates/squid/squid.conf.j2
index b953c8b18..4e3d702a8 100644
--- a/data/templates/squid/squid.conf.j2
+++ b/data/templates/squid/squid.conf.j2
@@ -30,6 +30,14 @@ acl BLOCKDOMAIN dstdomain {{ domain }}
{% endfor %}
http_access deny BLOCKDOMAIN
{% endif %}
+
+{% if domain_noncache is vyos_defined %}
+{% for domain in domain_noncache %}
+acl NOCACHE dstdomain {{ domain }}
+{% endfor %}
+no_cache deny NOCACHE
+{% endif %}
+
{% if authentication is vyos_defined %}
{% if authentication.children is vyos_defined %}
auth_param basic children {{ authentication.children }}
diff --git a/data/templates/ssh/motd_ssh_dsa_warning.j2 b/data/templates/ssh/motd_ssh_dsa_warning.j2
new file mode 100644
index 000000000..2d4598fa8
--- /dev/null
+++ b/data/templates/ssh/motd_ssh_dsa_warning.j2
@@ -0,0 +1,8 @@
+{% if hostkey_algorithm is vyos_defined %}
+{% set tmp = hostkey_algorithm | select("in", deprecated_algos) %}
+{% if tmp %}
+{% set tmp = ssh_dsa_deprecation_warning ~ ' ' ~ tmp | join(', ') %}
+---
+{{ tmp | wordwrap(72) }}
+{% endif %}
+{% endif %}
diff --git a/data/templates/ssh/sshd_config.j2 b/data/templates/ssh/sshd_config.j2
index 2cf0494c4..32f7e23e7 100644
--- a/data/templates/ssh/sshd_config.j2
+++ b/data/templates/ssh/sshd_config.j2
@@ -57,9 +57,9 @@ ListenAddress {{ address }}
{% endfor %}
{% endif %}
-{% if ciphers is vyos_defined %}
-# Specifies the ciphers allowed for protocol version 2
-Ciphers {{ ciphers | join(',') }}
+{% if cipher is vyos_defined %}
+# Specifies allowed ciphers for protocol version 2
+Ciphers {{ cipher | join(',') }}
{% endif %}
{% if hostkey_algorithm is vyos_defined %}
@@ -72,6 +72,20 @@ HostKeyAlgorithms {{ hostkey_algorithm | join(',') }}
PubkeyAcceptedAlgorithms {{ pubkey_accepted_algorithm | join(',') }}
{% endif %}
+{% if fido is vyos_defined %}
+{% set configured_pubkey_options = [] %}
+{% if fido.pin_required is vyos_defined %}
+{% do configured_pubkey_options.append('verify-required') %}
+{% endif %}
+{% if fido.touch_required is vyos_defined %}
+{% do configured_pubkey_options.append('touch-required') %}
+{% endif %}
+{% if configured_pubkey_options | length > 0 %}
+# Sets one or more public key authentication options.
+PubkeyAuthOptions {{ configured_pubkey_options | join(' ') }}
+{% endif %}
+{% endif %}
+
{% if mac is vyos_defined %}
# Specifies the available MAC (message authentication code) algorithms
MACs {{ mac | join(',') }}
@@ -110,3 +124,19 @@ ClientAliveInterval {{ client_keepalive_interval }}
{% if rekey.data is vyos_defined %}
RekeyLimit {{ rekey.data }}M {{ rekey.time + 'M' if rekey.time is vyos_defined }}
{% endif %}
+
+{% if trusted_user_ca is vyos_defined %}
+# Specifies a file containing public keys of certificate authorities that are
+# trusted to sign user certificates for authentication
+TrustedUserCAKeys {{ get_default_config_file('sshd_user_ca') }}
+
+# The default is "none", i.e. not to use a principals file - in this case, the
+# username of the user must appear in a certificate's principals list for it
+# to be accepted. ".ssh/authorized_principals" means a per-user configuration,
+# relative to $HOME.
+{% set filename = 'none' %}
+{% if has_principals is vyos_defined %}
+{% set filename = '.ssh/authorized_principals' %}
+{% endif %}
+AuthorizedPrincipalsFile {{ filename }}
+{% endif %}
diff --git a/data/templates/system/watchdog.conf.j2 b/data/templates/system/watchdog.conf.j2
new file mode 100644
index 000000000..d5f7e5ec4
--- /dev/null
+++ b/data/templates/system/watchdog.conf.j2
@@ -0,0 +1,5 @@
+### Autogenerated by system_watchdog.py ###
+[Manager]
+RuntimeWatchdogSec={{ timeout }}
+ShutdownWatchdogSec={{ shutdown_timeout }}
+RebootWatchdogSec={{ reboot_timeout }}
diff --git a/data/templates/telegraf/syslog_telegraf.j2 b/data/templates/telegraf/syslog_telegraf.j2
index cdcbd92a4..4fe6382ab 100644
--- a/data/templates/telegraf/syslog_telegraf.j2
+++ b/data/templates/telegraf/syslog_telegraf.j2
@@ -2,4 +2,8 @@
$ModLoad omuxsock
$OMUxSockSocket /run/telegraf/telegraf_syslog.sock
+{% if telegraf.loki is vyos_defined or telegraf.splunk is vyos_defined %}
+*.info;*.notice :omuxsock:
+{% else %}
*.notice :omuxsock:
+{% endif %}
diff --git a/data/templates/telegraf/telegraf.j2 b/data/templates/telegraf/telegraf.j2
index 535e3a347..5d61c554e 100644
--- a/data/templates/telegraf/telegraf.j2
+++ b/data/templates/telegraf/telegraf.j2
@@ -42,17 +42,24 @@
### End InfluxDB2 ###
{% endif %}
{% if loki is vyos_defined %}
+{% set parsed = loki.url | parse_url %}
+{% set base_url = parsed.scheme ~ '://' ~ parsed.hostname %}
+{% set endpoint = parsed.path if parsed.path and parsed.path != '/' else '' %}
### Loki ###
[[outputs.loki]]
## The domain of Loki
- domain = "{{ loki.url }}:{{ loki.port }}"
+ domain = "{{ base_url }}:{{ loki.port }}"
+{% if endpoint %}
+ ## Endpoint to write api
+ endpoint = "{{ endpoint }}"
+{% endif %}
{% if loki.authentication.username is vyos_defined and loki.authentication.password is vyos_defined %}
## Basic Authentication
username = "{{ loki.authentication.username }}"
password = "{{ loki.authentication.password }}"
{% endif %}
{% if loki.metric_name_label is vyos_defined %}
-metric_name_label = "{{ loki.metric_name_label }}"
+ metric_name_label = "{{ loki.metric_name_label }}"
{% endif %}
### End Loki ###
{% endif %}
diff --git a/data/templates/vpp/override.conf.j2 b/data/templates/vpp/override.conf.j2
new file mode 100644
index 000000000..01bfe3e3a
--- /dev/null
+++ b/data/templates/vpp/override.conf.j2
@@ -0,0 +1,18 @@
+[Unit]
+After=
+After=vyos-router.service
+ConditionPathExists=
+ConditionPathExists=/run/vpp/vpp.conf
+OnFailure=vpp-failure-handler.service
+
+[Service]
+EnvironmentFile=
+ExecStart=
+ExecStart=/usr/bin/vpp -c /run/vpp/vpp.conf
+WorkingDirectory=
+WorkingDirectory=/run/vpp
+Restart=no
+Type=notify
+# T8011 avoid duplicating logs
+StandardOutput=null
+StandardError=null
diff --git a/data/templates/vpp/startup.conf.j2 b/data/templates/vpp/startup.conf.j2
new file mode 100644
index 000000000..82d3753ae
--- /dev/null
+++ b/data/templates/vpp/startup.conf.j2
@@ -0,0 +1,193 @@
+# Generated by ${vyos_conf_scripts_dir}/vpp.py
+
+unix {
+ nodaemon
+ log /var/log/vpp.log
+ full-coredump
+ cli-listen /run/vpp/cli.sock
+ gid vpp
+ systemd-notify
+ # exec /etc/vpp/bootstrap.vpp
+{% if poll_sleep_usec is vyos_defined %}
+ poll-sleep-usec {{ poll_sleep_usec }}
+{% endif %}
+}
+
+{% if cpu is vyos_defined %}
+cpu {
+{% if cpu.main_core is vyos_defined %}
+ main-core {{ cpu.main_core }}
+{% endif %}
+{% if cpu.corelist_workers is vyos_defined %}
+ corelist-workers {{ cpu.corelist_workers }}
+{% endif %}
+}
+{% endif %}
+
+{% if resource_allocation.buffers is vyos_defined %}
+buffers {
+{% if resource_allocation.buffers.buffers_per_numa is vyos_defined %}
+ buffers-per-numa {{ resource_allocation.buffers.buffers_per_numa }}
+{% endif %}
+{% if resource_allocation.buffers.data_size is vyos_defined %}
+ default data-size {{ resource_allocation.buffers.data_size }}
+{% endif %}
+{% if resource_allocation.buffers.page_size is vyos_defined %}
+ page-size {{ resource_allocation.buffers.page_size }}
+{% endif %}
+}
+{% endif %}
+
+{% if resource_allocation.ipv6 is vyos_defined %}
+ip6 {
+{% if resource_allocation.ipv6.hash_buckets is vyos_defined %}
+ hash-buckets {{ resource_allocation.ipv6.hash_buckets }}
+{% endif %}
+{% if resource_allocation.ipv6.heap_size is vyos_defined %}
+ heap-size {{ resource_allocation.ipv6.heap_size }}
+{% endif %}
+}
+{% endif %}
+
+{% if resource_allocation.mac_limit is vyos_defined %}
+l2learn {
+ limit {{ resource_allocation.mac_limit }}
+}
+{% endif %}
+
+{% if logging is vyos_defined %}
+logging {
+{% if logging.default_level is vyos_defined %}
+ default-log-level {{ logging.default_level }}
+ default-syslog-log-level {{ logging.default_level }}
+{% endif %}
+}
+{% endif %}
+
+{% if resource_allocation.memory.physmem_max_size is vyos_defined %}
+physmem {
+ max-size {{ resource_allocation.memory.physmem_max_size }}
+}
+{% endif %}
+
+plugins {
+ plugin default { disable }
+ plugin avf_plugin.so { enable }
+ plugin dpdk_plugin.so { enable }
+ plugin vmxnet3_plugin.so { enable }
+ plugin lacp_plugin.so { enable }
+ plugin linux_cp_plugin.so { enable }
+ plugin linux_nl_plugin.so { enable }
+ plugin pppoe_plugin.so { enable }
+ # Flow
+ plugin flowprobe_plugin.so { enable }
+ plugin sflow_plugin.so { enable }
+ # NAT uncomment if needed
+ # plugin cnat_plugin.so { enable }
+ plugin nat_plugin.so { enable }
+ plugin nat44_ei_plugin.so { enable }
+ plugin det44_plugin.so { enable }
+ # plugin nat44_ei_plugin.so { enable }
+ # plugin nat64_plugin.so { enable }
+ # plugin nat66_plugin.so { enable }
+ # plugin pnat_plugin.so { enable }
+ # Tunnels
+ plugin geneve_plugin.so { enable }
+ plugin gre_plugin.so { enable }
+ plugin vxlan_plugin.so { enable }
+ # Secure
+ # plugin ikev2_plugin.so { enable }
+ # plugin dns_plugin.so { enable } # Probably required for FQDN peers
+ # plugin wireguard_plugin.so { enable }
+ # ACL
+ plugin acl_plugin.so { enable }
+ # DHCP plugin
+ plugin dhcp_plugin.so { enable }
+}
+
+
+crypto-engines {
+ default { disable }
+{% if ipsec_acceleration is vyos_defined %}
+ ipsecmb { enable }
+ native { enable }
+ openssl { enable }
+{% endif %}
+}
+
+
+linux-cp {
+ lcp-sync
+ lcp-auto-subint
+{% if ignore_kernel_routes is not vyos_defined %}
+ route-no-paths
+{% endif %}
+}
+
+{% set netlink_rx_buffers = 268435456 %}
+linux-nl {
+ nl-rx-buffer-size {{ netlink_rx_buffers }}
+}
+
+{% if resource_allocation.memory.stats is vyos_defined %}
+statseg {
+{% if resource_allocation.memory.stats.size is vyos_defined %}
+ size {{ resource_allocation.memory.stats.size }}
+{% endif %}
+{% if resource_allocation.memory.stats.page_size is vyos_defined %}
+ page-size {{ resource_allocation.memory.stats.page_size }}
+{% endif %}
+}
+{% endif %}
+
+{% if resource_allocation.memory is vyos_defined %}
+memory {
+{% if resource_allocation.memory.main_heap_size is vyos_defined %}
+ main-heap-size {{ resource_allocation.memory.main_heap_size }}
+{% endif %}
+{% if resource_allocation.memory.main_heap_page_size is vyos_defined %}
+ main-heap-page-size {{ resource_allocation.memory.main_heap_page_size }}
+{% endif %}
+{% if resource_allocation.buffers.page_size != '4K' %}
+ default-hugepage-size {{ resource_allocation.buffers.page_size }}
+{% endif %}
+}
+{% endif %}
+
+dpdk {
+ # Whitelist the fake PCI address 0000:00:00.0
+ # This prevents all devices from being added to VPP-DPDK by default
+ dev 0000:00:00.0
+{% for iface, iface_config in interface.items() %}
+{% if iface_config.driver == 'dpdk' %}
+ dev {{ iface_config.dpdk_options.dev_id }} {
+ name {{ iface }}
+{% if iface_config.num_rx_desc is vyos_defined %}
+ num-rx-desc {{ iface_config.num_rx_desc }}
+{% endif %}
+{% if iface_config.num_tx_desc is vyos_defined %}
+ num-tx-desc {{ iface_config.num_tx_desc }}
+{% endif %}
+{% if iface_config.num_rx_queues is vyos_defined %}
+ num-rx-queues {{ iface_config.num_rx_queues }}
+{% endif %}
+{% if iface_config.num_tx_queues is vyos_defined %}
+ num-tx-queues {{ iface_config.num_tx_queues }}
+{% endif %}
+ }
+{% endif %}
+{% endfor %}
+ uio-bind-force
+}
+
+{% if ipsec_acceleration is vyos_defined %}
+linux-xfrm-nl {
+ enable-route-mode-ipsec
+ interface ipsec
+ nl-rx-buffer-size {{ netlink_rx_buffers }}
+}
+{% endif %}
+
+pppoe {
+ enable-pass-nd-and-dhcpv6
+}
diff --git a/data/templates/wifi/hostapd.conf.j2 b/data/templates/wifi/hostapd.conf.j2
index 5f3757216..33a0703a3 100644
--- a/data/templates/wifi/hostapd.conf.j2
+++ b/data/templates/wifi/hostapd.conf.j2
@@ -3133,7 +3133,7 @@ own_ip_addr=127.0.0.1
# WAN Metrics
# format: <WAN Info>:<DL Speed>:<UL Speed>:<DL Load>:<UL Load>:<LMD>
-# WAN Info: B0-B1: Link Status, B2: Symmetric Link, B3: At Capabity
+# WAN Info: B0-B1: Link Status, B2: Symmetric Link, B3: At Capability
# (encoded as two hex digits)
# Link Status: 1 = Link up, 2 = Link down, 3 = Link in test state
# Downlink Speed: Estimate of WAN backhaul link current downlink speed in kbps;
@@ -3261,7 +3261,7 @@ own_ip_addr=127.0.0.1
# FST is the transfer of a session from a channel to another channel, in the
# same or different frequency bands.
#
-# For detals, see IEEE Std 802.11ad-2012.
+# For details, see IEEE Std 802.11ad-2012.
# Identifier of an FST Group the interface belongs to.
#fst_group_id=bond0
diff --git a/data/templates/zabbix-agent/zabbix-agent.conf.j2 b/data/templates/zabbix-agent/zabbix-agent.conf.j2
index e6dcef872..b8df2d177 100644
--- a/data/templates/zabbix-agent/zabbix-agent.conf.j2
+++ b/data/templates/zabbix-agent/zabbix-agent.conf.j2
@@ -75,3 +75,16 @@ Include={{ directory }}/*.conf
Timeout={{ timeout }}
{% endif %}
+{% if authentication is vyos_defined and authentication.mode is vyos_defined %}
+{% if authentication.mode == "pre-shared-secret" %}
+TLSConnect=psk
+TLSAccept=psk
+{% endif %}
+{% if authentication.psk.secret is vyos_defined %}
+TLSPSKFile={{ service_psk_file }}
+{% endif %}
+{% if authentication.psk.id is vyos_defined %}
+TLSPSKIdentity={{ authentication.psk.id }}
+{% endif %}
+{% endif %}
+
diff --git a/data/vyos-firewall-init.conf b/data/vyos-firewall-init.conf
index 3929edf0b..220b75652 100644
--- a/data/vyos-firewall-init.conf
+++ b/data/vyos-firewall-init.conf
@@ -17,7 +17,7 @@ table inet mangle {
table raw {
chain VYOS_TCP_MSS {
- type filter hook forward priority -300; policy accept;
+ type filter hook postrouting priority -300; policy accept;
}
chain vyos_global_rpfilter {
@@ -37,7 +37,7 @@ table raw {
table ip6 raw {
chain VYOS_TCP_MSS {
- type filter hook forward priority -300; policy accept;
+ type filter hook postrouting priority -300; policy accept;
}
chain vyos_global_rpfilter {