summaryrefslogtreecommitdiff
path: root/data
diff options
context:
space:
mode:
Diffstat (limited to 'data')
-rw-r--r--data/config-mode-dependencies/vyos-1x.json8
-rw-r--r--data/config.boot.default53
-rw-r--r--data/configd-include.json109
-rw-r--r--data/op-mode-standardized.json6
-rw-r--r--data/templates/accel-ppp/chap-secrets.ipoe.j22
-rw-r--r--data/templates/accel-ppp/ipoe.config.j210
-rw-r--r--data/templates/accel-ppp/pppoe.config.j216
-rw-r--r--data/templates/aws/override_aws_gwlbtun.conf.j236
-rw-r--r--data/templates/chrony/chrony.conf.j217
-rw-r--r--data/templates/conntrack/nftables-helpers.j26
-rw-r--r--data/templates/conntrack/sysctl.conf.j219
-rw-r--r--data/templates/conntrackd/conntrackd.op-mode.j213
-rw-r--r--data/templates/dhcp-server/10-override.conf.j230
-rw-r--r--data/templates/dhcp-server/dhcpd.conf.j2251
-rw-r--r--data/templates/dhcp-server/dhcpdv6.conf.j2132
-rw-r--r--data/templates/dhcp-server/kea-ctrl-agent.conf.j214
-rw-r--r--data/templates/dhcp-server/kea-dhcp4.conf.j280
-rw-r--r--data/templates/dhcp-server/kea-dhcp6.conf.j261
-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/dns-forwarding/recursor.conf.lua.j228
-rw-r--r--data/templates/firewall/nftables-bridge.j285
-rw-r--r--data/templates/firewall/nftables-cgnat.j247
-rw-r--r--data/templates/firewall/nftables-defines.j210
-rw-r--r--data/templates/firewall/nftables-nat.j213
-rw-r--r--data/templates/firewall/nftables-nat66.j224
-rw-r--r--data/templates/firewall/nftables-zone.j256
-rwxr-xr-x[-rw-r--r--]data/templates/firewall/nftables.j2160
-rw-r--r--data/templates/firewall/sysctl-firewall.conf.j236
-rw-r--r--data/templates/frr/babeld.frr.j22
-rw-r--r--data/templates/frr/bgpd.frr.j228
-rw-r--r--data/templates/frr/daemons.frr.tmpl4
-rw-r--r--data/templates/frr/distribute_list_macro.j23
-rw-r--r--data/templates/frr/eigrpd.frr.j224
-rw-r--r--data/templates/frr/evpn.mh.frr.j228
-rw-r--r--data/templates/frr/fabricd.frr.j273
-rw-r--r--data/templates/frr/ipv6_distribute_list_macro.j23
-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.j27
-rw-r--r--data/templates/frr/pim6d.frr.j221
-rw-r--r--data/templates/frr/pimd.frr.j236
-rw-r--r--data/templates/frr/rpki.frr.j24
-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.j22
-rw-r--r--data/templates/frr/zebra.segment_routing.frr.j23
-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/https/nginx.default.j22
-rw-r--r--data/templates/ids/suricata.j21280
-rw-r--r--data/templates/ids/suricata_logrotate.j217
-rw-r--r--data/templates/ipsec/swanctl.conf.j26
-rw-r--r--data/templates/ipsec/swanctl/profile.j28
-rw-r--r--data/templates/ipsec/swanctl/remote_access.j29
-rw-r--r--data/templates/lldp/vyos.conf.j211
-rw-r--r--data/templates/load-balancing/haproxy.cfg.j219
-rw-r--r--data/templates/load-balancing/nftables-wlb.j264
-rw-r--r--data/templates/load-balancing/wlb.conf.j2134
-rw-r--r--data/templates/login/default_motd.j23
-rw-r--r--data/templates/login/motd_vyos_nonproduction.j24
-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/mdns-repeater/avahi-daemon.conf.j23
-rw-r--r--data/templates/nhrp/nftables.conf.j217
-rw-r--r--data/templates/nhrp/opennhrp.conf.j242
-rw-r--r--data/templates/ocserv/radius_conf.j22
-rw-r--r--data/templates/openvpn/server.conf.j225
-rw-r--r--data/templates/pmacct/uacctd.conf.j223
-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.j220
-rw-r--r--data/templates/prometheus/node_exporter.service.j225
-rw-r--r--data/templates/rsyslog/override.conf.j211
-rw-r--r--data/templates/rsyslog/rsyslog.conf.j2164
-rw-r--r--data/templates/sflow/hsflowd.conf.j23
-rw-r--r--data/templates/squid/squid.conf.j28
-rw-r--r--data/templates/ssh/sshd_config.j24
-rw-r--r--data/templates/stunnel/stunnel_config.j2118
-rw-r--r--data/templates/telegraf/syslog_telegraf.j24
-rw-r--r--data/templates/telegraf/telegraf.j22
-rw-r--r--data/templates/wifi/wpa_supplicant.conf.j214
-rw-r--r--data/templates/zabbix-agent/10-override.conf.j25
-rw-r--r--data/templates/zabbix-agent/zabbix-agent.conf.j213
85 files changed, 2886 insertions, 1046 deletions
diff --git a/data/config-mode-dependencies/vyos-1x.json b/data/config-mode-dependencies/vyos-1x.json
index 9cfbffd96..cbd14f7c6 100644
--- a/data/config-mode-dependencies/vyos-1x.json
+++ b/data/config-mode-dependencies/vyos-1x.json
@@ -26,13 +26,14 @@
"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"],
"sstp": ["vpn_sstp"],
- "sstpc": ["interfaces_sstpc"]
+ "sstpc": ["interfaces_sstpc"],
+ "stunnel": ["service_stunnel"]
},
"vpn_ipsec": {
"nhrp": ["protocols_nhrp"]
@@ -60,6 +61,9 @@
"wireless": ["interfaces_wireless"],
"wwan": ["interfaces_wwan"]
},
+ "system_wireless": {
+ "wireless": ["interfaces_wireless"]
+ },
"system_ip": {
"sysctl": ["system_sysctl"]
},
diff --git a/data/config.boot.default b/data/config.boot.default
new file mode 100644
index 000000000..db5d11ea1
--- /dev/null
+++ b/data/config.boot.default
@@ -0,0 +1,53 @@
+interfaces {
+ loopback lo {
+ }
+}
+service {
+ ntp {
+ allow-client {
+ address "127.0.0.0/8"
+ address "169.254.0.0/16"
+ address "10.0.0.0/8"
+ address "172.16.0.0/12"
+ address "192.168.0.0/16"
+ address "::1/128"
+ address "fe80::/10"
+ address "fc00::/7"
+ }
+ server time1.vyos.net {
+ }
+ server time2.vyos.net {
+ }
+ server time3.vyos.net {
+ }
+ }
+}
+system {
+ config-management {
+ commit-revisions "100"
+ }
+ console {
+ device ttyS0 {
+ speed "115200"
+ }
+ }
+ host-name "vyos"
+ login {
+ user vyos {
+ authentication {
+ encrypted-password "$6$QxPS.uk6mfo$9QBSo8u1FkH16gMyAVhus6fU3LOzvLR9Z9.82m3tiHFAxTtIkhaZSWssSgzt4v4dGAL8rhVQxTg0oAG9/q11h/"
+ plaintext-password ""
+ }
+ }
+ }
+ syslog {
+ local {
+ facility all {
+ level "info"
+ }
+ facility local7 {
+ level "debug"
+ }
+ }
+ }
+}
diff --git a/data/configd-include.json b/data/configd-include.json
deleted file mode 100644
index a13618313..000000000
--- a/data/configd-include.json
+++ /dev/null
@@ -1,109 +0,0 @@
-[
-"container.py",
-"firewall.py",
-"high-availability.py",
-"interfaces_bonding.py",
-"interfaces_bridge.py",
-"interfaces_dummy.py",
-"interfaces_ethernet.py",
-"interfaces_geneve.py",
-"interfaces_input.py",
-"interfaces_l2tpv3.py",
-"interfaces_loopback.py",
-"interfaces_macsec.py",
-"interfaces_openvpn.py",
-"interfaces_pppoe.py",
-"interfaces_pseudo-ethernet.py",
-"interfaces_sstpc.py",
-"interfaces_tunnel.py",
-"interfaces_virtual-ethernet.py",
-"interfaces_vti.py",
-"interfaces_vxlan.py",
-"interfaces_wireguard.py",
-"interfaces_wireless.py",
-"interfaces_wwan.py",
-"load-balancing_reverse-proxy.py",
-"load-balancing_wan.py",
-"nat.py",
-"nat64.py",
-"nat66.py",
-"pki.py",
-"policy.py",
-"policy_route.py",
-"policy_local-route.py",
-"protocols_babel.py",
-"protocols_bfd.py",
-"protocols_bgp.py",
-"protocols_eigrp.py",
-"protocols_failover.py",
-"protocols_igmp-proxy.py",
-"protocols_isis.py",
-"protocols_mpls.py",
-"protocols_nhrp.py",
-"protocols_ospf.py",
-"protocols_ospfv3.py",
-"protocols_pim.py",
-"protocols_pim6.py",
-"protocols_rip.py",
-"protocols_ripng.py",
-"protocols_rpki.py",
-"protocols_segment-routing.py",
-"protocols_static.py",
-"protocols_static_arp.py",
-"protocols_static_multicast.py",
-"protocols_static_neighbor-proxy.py",
-"qos.py",
-"service_broadcast-relay.py",
-"service_config-sync.py",
-"service_conntrack-sync.py",
-"service_console-server.py",
-"service_dhcp-relay.py",
-"service_dhcp-server.py",
-"service_dhcpv6-relay.py",
-"service_dhcpv6-server.py",
-"service_dns_dynamic.py",
-"service_dns_forwarding.py",
-"service_event-handler.py",
-"service_https.py",
-"service_ids_ddos-protection.py",
-"service_ipoe-server.py",
-"service_lldp.py",
-"service_mdns_repeater.py",
-"service_monitoring_telegraf.py",
-"service_monitoring_zabbix-agent.py",
-"service_ndp-proxy.py",
-"service_ntp.py",
-"service_pppoe-server.py",
-"service_router-advert.py",
-"service_salt-minion.py",
-"service_sla.py",
-"service_ssh.py",
-"service_tftp-server.py",
-"service_webproxy.py",
-"system_acceleration.py",
-"system_config-management.py",
-"system_conntrack.py",
-"system_console.py",
-"system_flow-accounting.py",
-"system_frr.py",
-"system_host-name.py",
-"system_ip.py",
-"system_ipv6.py",
-"system_lcd.py",
-"system_login_banner.py",
-"system_logs.py",
-"system_option.py",
-"system_proxy.py",
-"system_sflow.py",
-"system_sysctl.py",
-"system_syslog.py",
-"system_task-scheduler.py",
-"system_timezone.py",
-"system_update-check.py",
-"vpn_ipsec.py",
-"vpn_l2tp.py",
-"vpn_openconnect.py",
-"vpn_pptp.py",
-"vpn_sstp.py",
-"vrf.py"
-]
diff --git a/data/op-mode-standardized.json b/data/op-mode-standardized.json
index 911869d09..c2bfc3094 100644
--- a/data/op-mode-standardized.json
+++ b/data/op-mode-standardized.json
@@ -3,6 +3,7 @@
"bgp.py",
"bonding.py",
"bridge.py",
+"cgnat.py",
"config_mgmt.py",
"conntrack.py",
"container.py",
@@ -12,18 +13,19 @@
"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",
"system.py",
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 9729b295e..34dfa529a 100644
--- a/data/templates/accel-ppp/ipoe.config.j2
+++ b/data/templates/accel-ppp/ipoe.config.j2
@@ -38,6 +38,9 @@ level={{ log.level }}
[ipoe]
verbose=1
+{% 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,8 +58,11 @@ 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 }}
-{% if iface_config.vlan is vyos_defined %}
+{% 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 %}
{% endfor %}
diff --git a/data/templates/accel-ppp/pppoe.config.j2 b/data/templates/accel-ppp/pppoe.config.j2
index 6711f2ec9..2c4871a6b 100644
--- a/data/templates/accel-ppp/pppoe.config.j2
+++ b/data/templates/accel-ppp/pppoe.config.j2
@@ -31,10 +31,13 @@ copy=1
level={{ log.level }}
{% endif %}
-{% if authentication.mode is vyos_defined("noauth") %}
[auth]
+{% if authentication.mode is vyos_defined("noauth") %}
noauth=1
{% endif %}
+{% if authentication.any_login is vyos_defined %}
+any-login=1
+{% endif %}
[client-ip-range]
0.0.0.0/0
@@ -58,13 +61,24 @@ interface={{ iface }}
{% for vlan in iface_config.vlan %}
interface=re:^{{ iface }}\.{{ vlan | range_to_regex }}$
{% endfor %}
+{% if iface_config.combined is vyos_defined %}
+interface={{ iface }}
+{% endif %}
+{% if iface_config.vlan_mon is vyos_defined %}
vlan-mon={{ iface }},{{ iface_config.vlan | join(',') }}
+{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% if service_name %}
service-name={{ service_name | join(',') }}
{% endif %}
+{% if accept_any_service is vyos_defined %}
+accept-any-service=1
+{% endif %}
+{% if accept_blank_service is vyos_defined %}
+accept-blank-service=1
+{% endif %}
{% if pado_delay %}
{% set delay_without_sessions = pado_delay.delays_without_sessions[0] | default('0') %}
{% set pado_delay_param = namespace(value=delay_without_sessions) %}
diff --git a/data/templates/aws/override_aws_gwlbtun.conf.j2 b/data/templates/aws/override_aws_gwlbtun.conf.j2
new file mode 100644
index 000000000..4c566d852
--- /dev/null
+++ b/data/templates/aws/override_aws_gwlbtun.conf.j2
@@ -0,0 +1,36 @@
+{% set args = [] %}
+{% if script.on_create is vyos_defined %}
+{% set _ = args.append("-c " + script.on_create) %}
+{% endif %}
+{% if script.on_destroy is vyos_defined %}
+{% set _ = args.append("-r " + script.on_destroy) %}
+{% endif %}
+
+{% if status.port is vyos_defined %}
+{% set _ = args.append("-p " + status.port) %}
+{% endif %}
+
+{% if threads.tunnel is vyos_defined %}
+{% set _ = args.append("--tunthreads " + threads.tunnel) %}
+{% endif %}
+{% if threads.tunnel_affinity is vyos_defined %}
+{% set _ = args.append("--tunaffinity " + threads.tunnel_affinity) %}
+{% endif %}
+
+{% if threads.udp is vyos_defined %}
+{% set _ = args.append("--udpthreads " + threads.udp) %}
+{% endif %}
+{% if threads.udp_affinity is vyos_defined %}
+{% set _ = args.append("--udpaffinity " + threads.udp_affinity) %}
+{% endif %}
+
+[Unit]
+StartLimitIntervalSec=0
+After=vyos-router.service
+
+[Service]
+EnvironmentFile=
+ExecStart=/usr/bin/gwlbtun {{ args | join(' ') }}
+CapabilityBoundingSet=CAP_NET_ADMIN
+Restart=always
+RestartSec=10
diff --git a/data/templates/chrony/chrony.conf.j2 b/data/templates/chrony/chrony.conf.j2
index e3f078fdc..cc80e4d64 100644
--- a/data/templates/chrony/chrony.conf.j2
+++ b/data/templates/chrony/chrony.conf.j2
@@ -42,7 +42,7 @@ 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 %}
@@ -66,3 +66,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-helpers.j2 b/data/templates/conntrack/nftables-helpers.j2
index 433931162..63a0cc855 100644
--- a/data/templates/conntrack/nftables-helpers.j2
+++ b/data/templates/conntrack/nftables-helpers.j2
@@ -31,6 +31,12 @@
}
{% endif %}
+{% if modules.rtsp is vyos_defined and ipv4 %}
+ ct helper rtsp_tcp {
+ type "rtsp" protocol tcp;
+ }
+{% endif %}
+
{% if modules.sip is vyos_defined %}
ct helper sip_tcp {
type "sip" protocol tcp;
diff --git a/data/templates/conntrack/sysctl.conf.j2 b/data/templates/conntrack/sysctl.conf.j2
index 986f75c61..cd6c34ede 100644
--- a/data/templates/conntrack/sysctl.conf.j2
+++ b/data/templates/conntrack/sysctl.conf.j2
@@ -3,25 +3,8 @@
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_icmp_timeout = {{ timeout.icmp }}
-net.netfilter.nf_conntrack_generic_timeout = {{ timeout.other }}
-
-net.netfilter.nf_conntrack_tcp_timeout_close_wait = {{ timeout.tcp.close_wait }}
-net.netfilter.nf_conntrack_tcp_timeout_close = {{ timeout.tcp.close }}
-net.netfilter.nf_conntrack_tcp_timeout_established = {{ timeout.tcp.established }}
-net.netfilter.nf_conntrack_tcp_timeout_fin_wait = {{ timeout.tcp.fin_wait }}
-net.netfilter.nf_conntrack_tcp_timeout_last_ack = {{ timeout.tcp.last_ack }}
-net.netfilter.nf_conntrack_tcp_timeout_syn_recv = {{ timeout.tcp.syn_recv }}
-net.netfilter.nf_conntrack_tcp_timeout_syn_sent = {{ timeout.tcp.syn_sent }}
-net.netfilter.nf_conntrack_tcp_timeout_time_wait = {{ timeout.tcp.time_wait }}
-
-net.netfilter.nf_conntrack_udp_timeout = {{ timeout.udp.other }}
-net.netfilter.nf_conntrack_udp_timeout_stream = {{ timeout.udp.stream }}
-
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
diff --git a/data/templates/conntrackd/conntrackd.op-mode.j2 b/data/templates/conntrackd/conntrackd.op-mode.j2
deleted file mode 100644
index 82f7e2859..000000000
--- a/data/templates/conntrackd/conntrackd.op-mode.j2
+++ /dev/null
@@ -1,13 +0,0 @@
-Source Destination Protocol
-{% for parsed in data if parsed.flow.meta is vyos_defined %}
-{% for key in parsed.flow.meta %}
-{% if key['@direction'] == 'original' %}
-{% set saddr = key.layer3.src | bracketize_ipv6 %}
-{% set sport = key.layer4.sport %}
-{% set daddr = key.layer3.dst | bracketize_ipv6 %}
-{% set dport = key.layer4.dport %}
-{% set protocol = key.layer4['@protoname'] %}
-{{ "%-48s" | format(saddr ~ ':' ~ sport) }} {{ "%-48s" | format(daddr ~ ':' ~ dport) }} {{ protocol }}
-{% endif %}
-{% endfor %}
-{% endfor %}
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 1504b6808..000000000
--- a/data/templates/dhcp-server/10-override.conf.j2
+++ /dev/null
@@ -1,30 +0,0 @@
-### Autogenerated by dhcp_server.py ###
-{% set lease_file = '/config/dhcpd.leases' %}
-[Unit]
-Description=ISC DHCP IPv4 server
-Documentation=man:dhcpd(8)
-RequiresMountsFor=/run
-ConditionPathExists=
-ConditionPathExists=/run/dhcp-server/dhcpd.conf
-After=
-After=vyos-router.service
-
-[Service]
-Type=forking
-WorkingDirectory=
-WorkingDirectory=/run/dhcp-server
-RuntimeDirectory=dhcp-server
-RuntimeDirectoryPreserve=yes
-Environment=PID_FILE=/run/dhcp-server/dhcpd.pid CONFIG_FILE=/run/dhcp-server/dhcpd.conf LEASE_FILE={{ lease_file }}
-PIDFile=/run/dhcp-server/dhcpd.pid
-ExecStartPre=/bin/sh -ec '\
-touch ${LEASE_FILE}; \
-chown dhcpd:vyattacfg ${LEASE_FILE}* ; \
-chmod 664 ${LEASE_FILE}* ; \
-/usr/sbin/dhcpd -4 -t -T -q -user dhcpd -group vyattacfg -pf ${PID_FILE} -cf ${CONFIG_FILE} -lf ${LEASE_FILE} '
-ExecStart=
-ExecStart=/usr/sbin/dhcpd -4 -q -user dhcpd -group vyattacfg -pf ${PID_FILE} -cf ${CONFIG_FILE} -lf ${LEASE_FILE}
-Restart=always
-
-[Install]
-WantedBy=multi-user.target
diff --git a/data/templates/dhcp-server/dhcpd.conf.j2 b/data/templates/dhcp-server/dhcpd.conf.j2
deleted file mode 100644
index d00837389..000000000
--- a/data/templates/dhcp-server/dhcpd.conf.j2
+++ /dev/null
@@ -1,251 +0,0 @@
-### Autogenerated by dhcp_server.py ###
-
-# For options please consult the following website:
-# https://www.isc.org/wp-content/uploads/2017/08/dhcp43options.html
-#
-# log-facility local7;
-{% if hostfile_update is vyos_defined %}
-on release {
- set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name);
- set ClientIp = binary-to-ascii(10, 8, ".",leased-address);
- execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "release", "", ClientIp, "", "");
-}
-on expiry {
- set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name);
- set ClientIp = binary-to-ascii(10, 8, ".",leased-address);
- execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "release", "", ClientIp, "", "");
-}
-{% endif %}
-
-{{ 'use-host-decl-names on;' if host_decl_name is vyos_defined }}
-ddns-update-style {{ 'interim' if dynamic_dns_update is vyos_defined else 'none' }};
-option rfc3442-static-route code 121 = array of integer 8;
-option windows-static-route code 249 = array of integer 8;
-option wpad-url code 252 = text;
-option rfc8925-ipv6-only-preferred code 108 = unsigned integer 32;
-
-# Vendor specific options - Ubiquiti Networks
-option space ubnt;
-option ubnt.unifi-controller code 1 = ip-address;
-class "ubnt" {
- match if substring (option vendor-class-identifier , 0, 4) = "ubnt";
- option vendor-class-identifier "ubnt";
- vendor-option-space ubnt;
-}
-
-{% if global_parameters is vyos_defined %}
-# The following {{ global_parameters | length }} line(s) have been added as
-# global-parameters in the CLI and have not been validated !!!
-{% for parameter in global_parameters %}
-{{ parameter }}
-{% endfor %}
-
-{% endif %}
-{% if high_availability is vyos_defined %}
-# DHCP HA configuration
-{% set split_value = '256' if high_availability.mode == 'active-passive' else '128' %}
-failover peer "{{ high_availability.name }}" {
-{% if high_availability.status == 'primary' %}
- primary;
- mclt 1800;
- split {{ split_value }};
-{% elif high_availability.status == 'secondary' %}
- secondary;
-{% endif %}
- address {{ high_availability.source_address }};
- port 647;
- peer address {{ high_availability.remote }};
- peer port 647;
- max-response-delay 30;
- max-unacked-updates 10;
- load balance max seconds 3;
-}
-{% endif %}
-{% if listen_address is vyos_defined %}
-
-# DHCP server serving relay subnet, we need a connector to the real world
-{% for address in listen_address %}
-# Connected subnet statement for listen-address {{ address }}
-subnet {{ address | network_from_ipv4 }} netmask {{ address | netmask_from_ipv4 }} { }
-{% endfor %}
-{% endif %}
-
-# Shared network configration(s)
-{% if shared_network_name is vyos_defined %}
-{% for network, network_config in shared_network_name.items() if network_config.disable is not vyos_defined %}
-shared-network {{ network }} {
-{% if network_config.authoritative is vyos_defined %}
- authoritative;
-{% endif %}
-{% if network_config.name_server is vyos_defined %}
- option domain-name-servers {{ network_config.name_server | join(', ') }};
-{% endif %}
-{% if network_config.domain_name is vyos_defined %}
- option domain-name "{{ network_config.domain_name }}";
-{% endif %}
-{% if network_config.domain_search is vyos_defined %}
- option domain-search "{{ network_config.domain_search | join('", "') }}";
-{% endif %}
-{% if network_config.ntp_server is vyos_defined %}
- option ntp-servers {{ network_config.ntp_server | join(', ') }};
-{% endif %}
-{% if network_config.ping_check is vyos_defined %}
- ping-check true;
-{% endif %}
-{% if network_config.shared_network_parameters is vyos_defined %}
- # The following {{ network_config.shared_network_parameters | length }} line(s)
- # were added as shared-network-parameters in the CLI and have not been validated
-{% for parameter in network_config.shared_network_parameters %}
- {{ parameter }}
-{% endfor %}
-{% endif %}
-{% if network_config.subnet is vyos_defined %}
-{% for subnet, subnet_config in network_config.subnet.items() %}
-{% if subnet_config.description is vyos_defined %}
- # {{ subnet_config.description }}
-{% endif %}
- subnet {{ subnet | address_from_cidr }} netmask {{ subnet | netmask_from_cidr }} {
-{% if subnet_config.name_server is vyos_defined %}
- option domain-name-servers {{ subnet_config.name_server | join(', ') }};
-{% endif %}
-{% if subnet_config.domain_name is vyos_defined %}
- option domain-name "{{ subnet_config.domain_name }}";
-{% endif %}
-{% if subnet_config.domain_search is vyos_defined %}
- option domain-search "{{ subnet_config.domain_search | join('", "') }}";
-{% endif %}
-{% if subnet_config.ntp_server is vyos_defined %}
- option ntp-servers {{ subnet_config.ntp_server | join(', ') }};
-{% endif %}
-{% if subnet_config.pop_server is vyos_defined %}
- option pop-server {{ subnet_config.pop_server | join(', ') }};
-{% endif %}
-{% if subnet_config.smtp_server is vyos_defined %}
- option smtp-server {{ subnet_config.smtp_server | join(', ') }};
-{% endif %}
-{% if subnet_config.time_server is vyos_defined %}
- option time-servers {{ subnet_config.time_server | join(', ') }};
-{% endif %}
-{% if subnet_config.wins_server is vyos_defined %}
- option netbios-name-servers {{ subnet_config.wins_server | join(', ') }};
-{% endif %}
-{% if subnet_config.ipv6_only_preferred is vyos_defined %}
- option rfc8925-ipv6-only-preferred {{ subnet_config.ipv6_only_preferred }};
-{% endif %}
-{% if subnet_config.static_route is vyos_defined %}
-{% set static_default_route = '' %}
-{% if subnet_config.default_router is vyos_defined %}
-{% set static_default_route = ', ' ~ '0.0.0.0/0' | isc_static_route(subnet_config.default_router) %}
-{% endif %}
-{% if subnet_config.static_route is vyos_defined %}
-{% set rfc3442_routes = [] %}
-{% for route, route_options in subnet_config.static_route.items() %}
-{% set rfc3442_routes = rfc3442_routes.append(route | isc_static_route(route_options.next_hop)) %}
-{% endfor %}
- option rfc3442-static-route {{ rfc3442_routes | join(', ') }}{{ static_default_route }};
- option windows-static-route {{ rfc3442_routes | join(', ') }};
-{% endif %}
-{% endif %}
-{% if subnet_config.ip_forwarding is vyos_defined %}
- option ip-forwarding true;
-{% endif %}
-{% if subnet_config.default_router is vyos_defined %}
- option routers {{ subnet_config.default_router }};
-{% endif %}
-{% if subnet_config.server_identifier is vyos_defined %}
- option dhcp-server-identifier {{ subnet_config.server_identifier }};
-{% endif %}
-{% if subnet_config.subnet_parameters is vyos_defined %}
- # The following {{ subnet_config.subnet_parameters | length }} line(s) were added as
- # subnet-parameters in the CLI and have not been validated!!!
-{% for parameter in subnet_config.subnet_parameters %}
- {{ parameter }}
-{% endfor %}
-{% endif %}
-{% if subnet_config.tftp_server_name is vyos_defined %}
- option tftp-server-name "{{ subnet_config.tftp_server_name }}";
-{% endif %}
-{% if subnet_config.bootfile_name is vyos_defined %}
- option bootfile-name "{{ subnet_config.bootfile_name }}";
- filename "{{ subnet_config.bootfile_name }}";
-{% endif %}
-{% if subnet_config.bootfile_server is vyos_defined %}
- next-server {{ subnet_config.bootfile_server }};
-{% endif %}
-{% if subnet_config.bootfile_size is vyos_defined %}
- option boot-size {{ subnet_config.bootfile_size }};
-{% endif %}
-{% if subnet_config.time_offset is vyos_defined %}
- option time-offset {{ subnet_config.time_offset }};
-{% endif %}
-{% if subnet_config.wpad_url is vyos_defined %}
- option wpad-url "{{ subnet_config.wpad_url }}";
-{% endif %}
-{% if subnet_config.client_prefix_length is vyos_defined %}
- option subnet-mask {{ ('0.0.0.0/' ~ subnet_config.client_prefix_length) | netmask_from_cidr }};
-{% endif %}
-{% if subnet_config.lease is vyos_defined %}
- default-lease-time {{ subnet_config.lease }};
- max-lease-time {{ subnet_config.lease }};
-{% endif %}
-{% if network_config.ping_check is not vyos_defined and subnet_config.ping_check is vyos_defined %}
- ping-check true;
-{% endif %}
-{% if subnet_config.static_mapping is vyos_defined %}
-{% for host, host_config in subnet_config.static_mapping.items() if host_config.disable is not vyos_defined %}
- host {{ host | replace('_','-') if host_decl_name is vyos_defined else network | replace('_','-') ~ '_' ~ host | replace('_','-') }} {
-{% if host_config.ip_address is vyos_defined %}
- fixed-address {{ host_config.ip_address }};
-{% endif %}
- hardware ethernet {{ host_config.mac_address }};
-{% if host_config.static_mapping_parameters is vyos_defined %}
- # The following {{ host_config.static_mapping_parameters | length }} line(s) were added
- # as static-mapping-parameters in the CLI and have not been validated
-{% for parameter in host_config.static_mapping_parameters %}
- {{ parameter }}
-{% endfor %}
-{% endif %}
- }
-{% endfor %}
-{% endif %}
-{% if subnet_config.vendor_option.ubiquiti.unifi_controller is vyos_defined %}
- option ubnt.unifi-controller {{ subnet_config.vendor_option.ubiquiti.unifi_controller }};
-{% endif %}
-{% if subnet_config.range is vyos_defined %}
-{# pool configuration can only be used if there follows a range option #}
- pool {
-{% endif %}
-{% if subnet_config.enable_failover is vyos_defined %}
- failover peer "{{ high_availability.name }}";
- deny dynamic bootp clients;
-{% endif %}
-{% if subnet_config.range is vyos_defined %}
-{% for range, range_options in subnet_config.range.items() %}
- range {{ range_options.start }} {{ range_options.stop }};
-{% endfor %}
-{% endif %}
-{% if subnet_config.range is vyos_defined %}
-{# pool configuration can only be used if there follows a range option #}
- }
-{% endif %}
- }
-{% endfor %}
-{% endif %}
- on commit {
- set shared-networkname = "{{ network }}";
-{% if hostfile_update is vyos_defined %}
- set ClientIp = binary-to-ascii(10, 8, ".", leased-address);
- set ClientMac = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6));
- set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name, "empty_hostname");
- if not (ClientName = "empty_hostname") {
- set ClientDomain = pick-first-value(config-option domain-name, "..YYZ!");
- execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "commit", ClientName, ClientIp, ClientMac, ClientDomain);
- } else {
- log(concat("Hostname is not defined for client with IP: ", ClientIP, " MAC: ", ClientMac));
- }
-{% endif %}
- }
-}
-
-{% endfor %}
-{% endif %}
diff --git a/data/templates/dhcp-server/dhcpdv6.conf.j2 b/data/templates/dhcp-server/dhcpdv6.conf.j2
deleted file mode 100644
index 5c3471316..000000000
--- a/data/templates/dhcp-server/dhcpdv6.conf.j2
+++ /dev/null
@@ -1,132 +0,0 @@
-### Autogenerated by dhcpv6_server.py ###
-
-# For options please consult the following website:
-# https://www.isc.org/wp-content/uploads/2017/08/dhcp43options.html
-
-log-facility local7;
-{% if preference is vyos_defined %}
-option dhcp6.preference {{ preference }};
-{% endif %}
-
-{% if global_parameters.name_server is vyos_defined %}
-option dhcp6.name-servers {{ global_parameters.name_server | join(', ') }};
-{% endif %}
-
-# Vendor specific options - Cisco
-option space cisco code width 2 length width 2;
-option cisco.tftp-servers code 1 = array of ip6-address;
-option vsio.cisco code 9 = encapsulate cisco;
-
-# Shared network configration(s)
-{% if shared_network_name is vyos_defined %}
-{% for network, network_config in shared_network_name.items() if network_config.disable is not vyos_defined %}
-shared-network {{ network }} {
-{% if network_config.common_options is vyos_defined %}
-{% if network_config.common_options.info_refresh_time is vyos_defined %}
- option dhcp6.info-refresh-time {{ network_config.common_options.info_refresh_time }};
-{% endif %}
-{% if network_config.common_options.domain_search is vyos_defined %}
- option dhcp6.domain-search "{{ network_config.common_options.domain_search | join('", "') }}";
-{% endif %}
-{% if network_config.common_options.name_server is vyos_defined %}
- option dhcp6.name-servers {{ network_config.common_options.name_server | join(', ') }};
-{% endif %}
-{% endif %}
-{% if network_config.subnet is vyos_defined %}
-{% for subnet, subnet_config in network_config.subnet.items() %}
- subnet6 {{ subnet }} {
-{% if subnet_config.address_range is vyos_defined %}
-{% if subnet_config.address_range.prefix is vyos_defined %}
-{% for prefix, prefix_config in subnet_config.address_range.prefix.items() %}
- range6 {{ prefix }} {{ "temporary" if prefix_config.temporary is vyos_defined }};
-{% endfor %}
-{% endif %}
-{% if subnet_config.address_range.start is vyos_defined %}
-{% for address, address_config in subnet_config.address_range.start.items() %}
- range6 {{ address }} {{ address_config.stop }};
-{% endfor %}
-{% endif %}
-{% endif %}
-{% if subnet_config.domain_search is vyos_defined %}
- option dhcp6.domain-search "{{ subnet_config.domain_search | join('", "') }}";
-{% endif %}
-{% if subnet_config.lease_time is vyos_defined %}
-{% if subnet_config.lease_time.default is vyos_defined %}
- default-lease-time {{ subnet_config.lease_time.default }};
-{% endif %}
-{% if subnet_config.lease_time.maximum is vyos_defined %}
- max-lease-time {{ subnet_config.lease_time.maximum }};
-{% endif %}
-{% if subnet_config.lease_time.minimum is vyos_defined %}
- min-lease-time {{ subnet_config.lease_time.minimum }};
-{% endif %}
-{% endif %}
-{% if subnet_config.name_server is vyos_defined %}
- option dhcp6.name-servers {{ subnet_config.name_server | join(', ') }};
-{% endif %}
-{% if subnet_config.nis_domain is vyos_defined %}
- option dhcp6.nis-domain-name "{{ subnet_config.nis_domain }}";
-{% endif %}
-{% if subnet_config.nis_server is vyos_defined %}
- option dhcp6.nis-servers {{ subnet_config.nis_server | join(', ') }};
-{% endif %}
-{% if subnet_config.nisplus_domain is vyos_defined %}
- option dhcp6.nisp-domain-name "{{ subnet_config.nisplus_domain }}";
-{% endif %}
-{% if subnet_config.nisplus_server is vyos_defined %}
- option dhcp6.nisp-servers {{ subnet_config.nisplus_server | join(', ') }};
-{% endif %}
-{% if subnet_config.sip_server is vyos_defined %}
-{% set server_ip = [] %}
-{% set server_fqdn = [] %}
-{% for address in subnet_config.sip_server %}
-{% if address | is_ipv6 %}
-{% set server_ip = server_ip.append(address) %}
-{% else %}
-{% set server_fqdn = server_fqdn.append(address) %}
-{% endif %}
-{% endfor %}
-{% if server_ip is vyos_defined and server_ip | length > 0 %}
- option dhcp6.sip-servers-addresses {{ server_ip | join(', ') }};
-{% endif %}
-{% if server_fqdn is vyos_defined and server_fqdn | length > 0 %}
- option dhcp6.sip-servers-names "{{ server_fqdn | join('", "') }}";
-{% endif %}
-{% endif %}
-{% if subnet_config.sntp_server is vyos_defined %}
- option dhcp6.sntp-servers {{ subnet_config.sntp_server | join(', ') }};
-{% endif %}
-{% if subnet_config.prefix_delegation.start is vyos_defined %}
-{% for prefix, prefix_config in subnet_config.prefix_delegation.start.items() %}
- prefix6 {{ prefix }} {{ prefix_config.stop }} /{{ prefix_config.prefix_length }};
-{% endfor %}
-{% endif %}
-{% if subnet_config.static_mapping is vyos_defined %}
-
- # begin configuration of static client mappings
-{% for host, host_config in subnet_config.static_mapping.items() if host_config.disable is not vyos_defined %}
- host {{ network | replace('_','-') }}_{{ host | replace('_','-') }} {
-{% if host_config.identifier is vyos_defined %}
- host-identifier option dhcp6.client-id {{ host_config.identifier }};
-{% endif %}
-{% if host_config.ipv6_address is vyos_defined %}
- fixed-address6 {{ host_config.ipv6_address }};
-{% endif %}
-{% if host_config.ipv6_prefix is vyos_defined %}
- fixed-prefix6 {{ host_config.ipv6_prefix }};
-{% endif %}
- }
-{% endfor %}
-{% endif %}
-{% if subnet_config.vendor_option.cisco.tftp_server is vyos_defined %}
- option cisco.tftp-servers {{ subnet_config.vendor_option.cisco.tftp_server | join(', ') }};
-{% endif %}
- }
-{% endfor %}
-{% endif %}
- on commit {
- set shared-networkname = "{{ network }}";
- }
-}
-{% endfor %}
-{% endif %}
diff --git a/data/templates/dhcp-server/kea-ctrl-agent.conf.j2 b/data/templates/dhcp-server/kea-ctrl-agent.conf.j2
new file mode 100644
index 000000000..b37cf4798
--- /dev/null
+++ b/data/templates/dhcp-server/kea-ctrl-agent.conf.j2
@@ -0,0 +1,14 @@
+{
+ "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-dhcp4.conf.j2 b/data/templates/dhcp-server/kea-dhcp4.conf.j2
new file mode 100644
index 000000000..2e10d58e0
--- /dev/null
+++ b/data/templates/dhcp-server/kea-dhcp4.conf.j2
@@ -0,0 +1,80 @@
+{
+ "Dhcp4": {
+ "interfaces-config": {
+{% if listen_address is vyos_defined %}
+ "interfaces": {{ listen_address | kea_address_json }},
+ "dhcp-socket-type": "udp",
+{% elif listen_interface is vyos_defined %}
+ "interfaces": {{ listen_interface | tojson }},
+ "dhcp-socket-type": "raw",
+{% else %}
+ "interfaces": [ "*" ],
+ "dhcp-socket-type": "raw",
+{% endif %}
+ "service-sockets-max-retries": 60,
+ "service-sockets-retry-wait-time": 5000
+ },
+ "control-socket": {
+ "socket-type": "unix",
+ "socket-name": "/run/kea/dhcp4-ctrl-socket"
+ },
+ "lease-database": {
+ "type": "memfile",
+ "persist": true,
+ "name": "{{ lease_file }}"
+ },
+ "option-def": [
+ {
+ "name": "rfc3442-static-route",
+ "code": 121,
+ "type": "record",
+ "array": true,
+ "record-types": "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"
+ },
+ {
+ "name": "wpad-url",
+ "code": 252,
+ "type": "string"
+ },
+ {
+ "name": "unifi-controller",
+ "code": 1,
+ "type": "ipv4-address",
+ "space": "ubnt"
+ }
+ ],
+ "hooks-libraries": [
+{% if high_availability is vyos_defined %}
+ {
+ "library": "/usr/lib/{{ machine }}-linux-gnu/kea/hooks/libdhcp_ha.so",
+ "parameters": {
+ "high-availability": [{{ high_availability | kea_high_availability_json }}]
+ }
+ },
+{% endif %}
+{% if hostfile_update is vyos_defined %}
+ {
+ "library": "/usr/lib/{{ machine }}-linux-gnu/kea/hooks/libdhcp_run_script.so",
+ "parameters": {
+ "name": "/usr/libexec/vyos/system/on-dhcp-event.sh",
+ "sync": false
+ }
+ },
+{% 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 }}
+{% endif %}
+ }
+}
diff --git a/data/templates/dhcp-server/kea-dhcp6.conf.j2 b/data/templates/dhcp-server/kea-dhcp6.conf.j2
new file mode 100644
index 000000000..4745d693c
--- /dev/null
+++ b/data/templates/dhcp-server/kea-dhcp6.conf.j2
@@ -0,0 +1,61 @@
+{
+ "Dhcp6": {
+ "interfaces-config": {
+{% if listen_interface is vyos_defined %}
+ "interfaces": {{ listen_interface | tojson }},
+{% else %}
+ "interfaces": [ "*" ],
+{% endif %}
+ "service-sockets-max-retries": 60,
+ "service-sockets-retry-wait-time": 5000
+ },
+ "control-socket": {
+ "socket-type": "unix",
+ "socket-name": "/run/kea/dhcp6-ctrl-socket"
+ },
+ "lease-database": {
+ "type": "memfile",
+ "persist": true,
+ "name": "{{ lease_file }}"
+ },
+ "hooks-libraries": [
+{% if disable_route_autoinstall is not vyos_defined %}
+ {
+ "library": "/usr/lib/{{ machine }}-linux-gnu/kea/hooks/libdhcp_run_script.so",
+ "parameters": {
+ "name": "/usr/libexec/vyos/system/on-dhcpv6-event.sh",
+ "sync": false
+ }
+ },
+{% endif %}
+ {
+ "library": "/usr/lib/{{ machine }}-linux-gnu/kea/hooks/libdhcp_lease_cmds.so",
+ "parameters": {}
+ }
+ ],
+ "option-data": [
+{% if global_parameters.name_server is vyos_defined %}
+ {
+ "name": "dns-servers",
+ "code": 23,
+ "space": "dhcp6",
+ "csv-format": true,
+ "data": "{{ global_parameters.name_server | join(", ") }}"
+ }{{ ',' if preference is vyos_defined else '' }}
+{% endif %}
+{% if preference is vyos_defined %}
+ {
+ "name": "preference",
+ "code": 7,
+ "space": "dhcp6",
+ "csv-format": true,
+ "data": "{{ preference }}"
+ }
+{% endif %}
+ ],
+{% if shared_network_name is vyos_defined %}
+ "shared-networks": {{ shared_network_name | kea6_shared_network_json }}
+{% endif %}
+
+ }
+}
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/dns-forwarding/recursor.conf.lua.j2 b/data/templates/dns-forwarding/recursor.conf.lua.j2
index 8026442c7..622283ad8 100644
--- a/data/templates/dns-forwarding/recursor.conf.lua.j2
+++ b/data/templates/dns-forwarding/recursor.conf.lua.j2
@@ -6,3 +6,31 @@ dofile("/usr/share/pdns-recursor/lua-config/rootkeys.lua")
-- Load lua from vyos-hostsd --
dofile("{{ config_dir }}/recursor.vyos-hostsd.conf.lua")
+
+-- ZoneToCache --
+{% if zone_cache is vyos_defined %}
+{% set option_mapping = {
+ 'refresh': 'refreshPeriod',
+ 'retry_interval': 'retryOnErrorPeriod',
+ 'max_zone_size': 'maxReceivedMBytes'
+} %}
+{% for name, conf in zone_cache.items() %}
+{% set source = conf.source.items() | first %}
+{% set settings = [] %}
+{% for key, val in conf.options.items() %}
+{% set mapped_key = option_mapping.get(key, key) %}
+{% if key == 'refresh' %}
+{% set val = val['interval'] %}
+{% endif %}
+{% if key in ['dnssec', 'zonemd'] %}
+{% set _ = settings.append(mapped_key ~ ' = "' ~ val ~ '"') %}
+{% else %}
+{% set _ = settings.append(mapped_key ~ ' = ' ~ val) %}
+{% endif %}
+{% endfor %}
+
+zoneToCache("{{ name }}", "{{ source[0] }}", "{{ source[1] }}", { {{ settings | join(', ') }} })
+
+{% endfor %}
+
+{% endif %}
diff --git a/data/templates/firewall/nftables-bridge.j2 b/data/templates/firewall/nftables-bridge.j2
index dec027bf9..1975fb9b0 100644
--- a/data/templates/firewall/nftables-bridge.j2
+++ b/data/templates/firewall/nftables-bridge.j2
@@ -1,9 +1,13 @@
+{% import 'firewall/nftables-defines.j2' as group_tmpl %}
{% macro bridge(bridge) %}
{% set ns = namespace(sets=[]) %}
{% if bridge.forward is vyos_defined %}
{% for prior, conf in bridge.forward.items() %}
chain VYOS_FORWARD_{{ prior }} {
type filter hook forward priority {{ prior }}; policy accept;
+{% if global_options.state_policy is vyos_defined %}
+ jump VYOS_STATE_POLICY
+{% endif %}
{% if conf.rule is vyos_defined %}
{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
{{ rule_conf | nft_rule('FWD', prior, rule_id, 'bri') }}
@@ -17,6 +21,46 @@
{% endfor %}
{% endif %}
+{% if bridge.input is vyos_defined %}
+{% for prior, conf in bridge.input.items() %}
+ chain VYOS_INPUT_{{ prior }} {
+ type filter hook input priority {{ prior }}; policy accept;
+{% if global_options.state_policy is vyos_defined %}
+ jump VYOS_STATE_POLICY
+{% endif %}
+{% if conf.rule is vyos_defined %}
+{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
+ {{ rule_conf | nft_rule('INP', prior, rule_id, 'bri') }}
+{% if rule_conf.recent is vyos_defined %}
+{% set ns.sets = ns.sets + ['INP_' + prior + '_' + rule_id] %}
+{% endif %}
+{% endfor %}
+{% endif %}
+ {{ conf | nft_default_rule('INP-filter', 'bri') }}
+ }
+{% endfor %}
+{% endif %}
+
+{% if bridge.output is vyos_defined %}
+{% for prior, conf in bridge.output.items() %}
+ chain VYOS_OUTUT_{{ prior }} {
+ type filter hook output priority {{ prior }}; policy accept;
+{% if global_options.state_policy is vyos_defined %}
+ jump VYOS_STATE_POLICY
+{% endif %}
+{% if conf.rule is vyos_defined %}
+{% 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, 'bri') }}
+{% if rule_conf.recent is vyos_defined %}
+{% set ns.sets = ns.sets + ['OUT_' + prior + '_' + rule_id] %}
+{% endif %}
+{% endfor %}
+{% endif %}
+ {{ conf | nft_default_rule('OUT-filter', 'bri') }}
+ }
+{% endfor %}
+{% endif %}
+
{% if bridge.name is vyos_defined %}
{% for name_text, conf in bridge.name.items() %}
chain NAME_{{ name_text }} {
@@ -32,4 +76,45 @@
}
{% endfor %}
{% endif %}
+
+{% for set_name in ns.sets %}
+ set RECENT_{{ set_name }} {
+ type ipv4_addr
+ size 65535
+ flags dynamic
+ }
+{% endfor %}
+{% for set_name in ip_fqdn %}
+ set FQDN_{{ set_name }} {
+ type ipv4_addr
+ flags interval
+ }
+{% endfor %}
+{% if geoip_updated.name is vyos_defined %}
+{% for setname in geoip_updated.name %}
+ set {{ setname }} {
+ type ipv4_addr
+ flags interval
+ }
+{% endfor %}
+{% endif %}
+
+{{ group_tmpl.groups(group, False, True) }}
+{{ group_tmpl.groups(group, True, True) }}
+
+{% 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') }}
+{% 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 %}
+
{% endmacro %}
diff --git a/data/templates/firewall/nftables-cgnat.j2 b/data/templates/firewall/nftables-cgnat.j2
new file mode 100644
index 000000000..79a8e3d5a
--- /dev/null
+++ b/data/templates/firewall/nftables-cgnat.j2
@@ -0,0 +1,47 @@
+#!/usr/sbin/nft -f
+
+add table ip cgnat
+flush table ip cgnat
+
+add map ip cgnat tcp_nat_map { type ipv4_addr: interval ipv4_addr . inet_service ; flags interval ;}
+add map ip cgnat udp_nat_map { type ipv4_addr: interval ipv4_addr . inet_service ; flags interval ;}
+add map ip cgnat icmp_nat_map { type ipv4_addr: interval ipv4_addr . inet_service ; flags interval ;}
+add map ip cgnat other_nat_map { type ipv4_addr: interval ipv4_addr ; flags interval ;}
+flush map ip cgnat tcp_nat_map
+flush map ip cgnat udp_nat_map
+flush map ip cgnat icmp_nat_map
+flush map ip cgnat other_nat_map
+
+table ip cgnat {
+ map tcp_nat_map {
+ type ipv4_addr : interval ipv4_addr . inet_service
+ flags interval
+ elements = { {{ proto_map_elements }} }
+ }
+
+ map udp_nat_map {
+ type ipv4_addr : interval ipv4_addr . inet_service
+ flags interval
+ elements = { {{ proto_map_elements }} }
+ }
+
+ map icmp_nat_map {
+ type ipv4_addr : interval ipv4_addr . inet_service
+ flags interval
+ elements = { {{ proto_map_elements }} }
+ }
+
+ map other_nat_map {
+ type ipv4_addr : interval ipv4_addr
+ flags interval
+ elements = { {{ other_map_elements }} }
+ }
+
+ chain POSTROUTING {
+ type nat hook postrouting priority srcnat; policy accept;
+ ip protocol tcp counter snat ip to ip saddr map @tcp_nat_map
+ ip protocol udp counter snat ip to ip saddr map @udp_nat_map
+ ip protocol icmp counter snat ip to ip saddr map @icmp_nat_map
+ counter snat ip to ip saddr map @other_nat_map
+ }
+}
diff --git a/data/templates/firewall/nftables-defines.j2 b/data/templates/firewall/nftables-defines.j2
index 8a75ab2d6..fa6cd74c0 100644
--- a/data/templates/firewall/nftables-defines.j2
+++ b/data/templates/firewall/nftables-defines.j2
@@ -1,7 +1,7 @@
{% macro groups(group, is_ipv6, is_l3) %}
{% if group is vyos_defined %}
{% set ip_type = 'ipv6_addr' if is_ipv6 else 'ipv4_addr' %}
-{% if group.address_group is vyos_defined and not is_ipv6 and is_l3 %}
+{% if group.address_group is vyos_defined and not is_ipv6 %}
{% for group_name, group_conf in group.address_group.items() %}
{% set includes = group_conf.include if group_conf.include is vyos_defined else [] %}
set A_{{ group_name }} {
@@ -14,7 +14,7 @@
}
{% endfor %}
{% endif %}
-{% if group.ipv6_address_group is vyos_defined and is_ipv6 and is_l3 %}
+{% if group.ipv6_address_group is vyos_defined and is_ipv6 %}
{% for group_name, group_conf in group.ipv6_address_group.items() %}
{% set includes = group_conf.include if group_conf.include is vyos_defined else [] %}
set A6_{{ group_name }} {
@@ -46,7 +46,7 @@
}
{% endfor %}
{% endif %}
-{% if group.network_group is vyos_defined and not is_ipv6 and is_l3 %}
+{% if group.network_group is vyos_defined and not is_ipv6 %}
{% for group_name, group_conf in group.network_group.items() %}
{% set includes = group_conf.include if group_conf.include is vyos_defined else [] %}
set N_{{ group_name }} {
@@ -59,7 +59,7 @@
}
{% endfor %}
{% endif %}
-{% if group.ipv6_network_group is vyos_defined and is_ipv6 and is_l3 %}
+{% if group.ipv6_network_group is vyos_defined and is_ipv6 %}
{% for group_name, group_conf in group.ipv6_network_group.items() %}
{% set includes = group_conf.include if group_conf.include is vyos_defined else [] %}
set N6_{{ group_name }} {
@@ -72,7 +72,7 @@
}
{% endfor %}
{% endif %}
-{% if group.port_group is vyos_defined and is_l3 %}
+{% if group.port_group is vyos_defined %}
{% for group_name, group_conf in group.port_group.items() %}
{% set includes = group_conf.include if group_conf.include is vyos_defined else [] %}
set P_{{ group_name }} {
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-nat66.j2 b/data/templates/firewall/nftables-nat66.j2
index 67eb2c109..09b5b6ac2 100644
--- a/data/templates/firewall/nftables-nat66.j2
+++ b/data/templates/firewall/nftables-nat66.j2
@@ -1,8 +1,11 @@
#!/usr/sbin/nft -f
+{% import 'firewall/nftables-defines.j2' as group_tmpl %}
+
{% if first_install is not vyos_defined %}
delete table ip6 vyos_nat
{% endif %}
+{% if deleted is not vyos_defined %}
table ip6 vyos_nat {
#
# Destination NAT66 rules build up here
@@ -10,11 +13,11 @@ table ip6 vyos_nat {
chain PREROUTING {
type nat hook prerouting priority -100; policy accept;
counter jump VYOS_DNPT_HOOK
-{% if destination.rule is vyos_defined %}
-{% for rule, config in destination.rule.items() if config.disable is not vyos_defined %}
- {{ config | nat_rule(rule, 'destination', ipv6=True) }}
-{% endfor %}
-{% endif %}
+{% if destination.rule is vyos_defined %}
+{% for rule, config in destination.rule.items() if config.disable is not vyos_defined %}
+ {{ config | nat_rule(rule, 'destination', ipv6=True) }}
+{% endfor %}
+{% endif %}
}
#
@@ -23,11 +26,11 @@ table ip6 vyos_nat {
chain POSTROUTING {
type nat hook postrouting priority 100; policy accept;
counter jump VYOS_SNPT_HOOK
-{% if source.rule is vyos_defined %}
-{% for rule, config in source.rule.items() if config.disable is not vyos_defined %}
+{% if source.rule is vyos_defined %}
+{% for rule, config in source.rule.items() if config.disable is not vyos_defined %}
{{ config | nat_rule(rule, 'source', ipv6=True) }}
-{% endfor %}
-{% endif %}
+{% endfor %}
+{% endif %}
}
chain VYOS_DNPT_HOOK {
@@ -37,4 +40,7 @@ table ip6 vyos_nat {
chain VYOS_SNPT_HOOK {
return
}
+
+{{ group_tmpl.groups(firewall_group, True, True) }}
}
+{% endif %}
diff --git a/data/templates/firewall/nftables-zone.j2 b/data/templates/firewall/nftables-zone.j2
index e78725079..645a38706 100644
--- a/data/templates/firewall/nftables-zone.j2
+++ b/data/templates/firewall/nftables-zone.j2
@@ -8,7 +8,14 @@
{% 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 | join(',') }} } counter jump VZONE_{{ zone_name }}
+{% endif %}
+{% if 'vrf' in zone_conf.member %}
+{% for vrf_name in zone_conf.member.vrf %}
+ oifname { {{ zone_conf['vrf_interfaces'][vrf_name] }} } counter jump VZONE_{{ zone_name }}
+{% endfor %}
+{% endif %}
{% endif %}
{% endfor %}
}
@@ -40,8 +47,15 @@
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 | join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf.firewall[fw_name] }}
+ iifname { {{ zone[from_zone].member.interface | join(",") }} } counter return
+{% endif %}
+{% if 'vrf' in zone[from_zone].member %}
+ iifname { {{ zone[from_zone].member.vrf | join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf.firewall[fw_name] }}
+ iifname { {{ zone[from_zone].member.vrf | join(",") }} } counter return
+{% endif %}
{% endfor %}
{% endif %}
{{ zone_conf | nft_default_rule('zone_' + zone_name, family) }}
@@ -50,23 +64,47 @@
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 | join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf.firewall[fw_name] }}
+ oifname { {{ zone[from_zone].member.interface | 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.firewall[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 | join(",") }} } counter {{ zone_conf | nft_intra_zone_action(ipv6) }}
+{% endif %}
+{% if 'vrf' in zone_conf.member %}
+ iifname { {{ zone_conf.member.vrf | 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 | join(",") }} } counter return
+{% endif %}
+{% if 'vrf' in zone_conf.member %}
+ iifname { {{ zone_conf.member.vrf | 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 | join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf.firewall[fw_name] }}
+ iifname { {{ zone[from_zone].member.interface | join(",") }} } counter return
+{% endif %}
+{% if 'vrf' in zone[from_zone].member %}
+ iifname { {{ zone[from_zone].member.vrf | join(",") }} } counter jump NAME{{ suffix }}_{{ from_conf.firewall[fw_name] }}
+ iifname { {{ zone[from_zone].member.vrf | join(",") }} } counter return
+{% endif %}
{% endif %}
{% endfor %}
{% endif %}
diff --git a/data/templates/firewall/nftables.j2 b/data/templates/firewall/nftables.j2
index 833df3a67..67473da8e 100644..100755
--- a/data/templates/firewall/nftables.j2
+++ b/data/templates/firewall/nftables.j2
@@ -57,7 +57,7 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('FWD-filter', 'ipv4') }}
+ {{ conf | nft_default_rule('FWD-' + prior, 'ipv4') }}
}
{% endfor %}
{% endif %}
@@ -77,7 +77,7 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('INP-filter', 'ipv4') }}
+ {{ conf | nft_default_rule('INP-' + prior, 'ipv4') }}
}
{% endfor %}
{% endif %}
@@ -86,7 +86,7 @@ table ip vyos_filter {
{% for prior, conf in ipv4.output.items() %}
chain VYOS_OUTPUT_{{ prior }} {
type filter hook output priority {{ prior }}; policy accept;
-{% if global_options.state_policy is vyos_defined %}
+{% if global_options.state_policy is vyos_defined and prior == 'filter' %}
jump VYOS_STATE_POLICY
{% endif %}
{% if conf.rule is vyos_defined %}
@@ -97,14 +97,11 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('OUT-filter', 'ipv4') }}
+ {{ conf | nft_default_rule('OUT-' + prior, 'ipv4') }}
}
{% endfor %}
{% endif %}
- chain VYOS_FRAG_MARK {
- type filter hook prerouting priority -450; policy accept;
- ip frag-off & 0x3fff != 0 meta mark set 0xffff1 return
- }
+
{% if ipv4.prerouting is vyos_defined %}
{% for prior, conf in ipv4.prerouting.items() %}
chain VYOS_PREROUTING_{{ prior }} {
@@ -117,11 +114,16 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('PRE-filter', 'ipv4') }}
+ {{ conf | nft_default_rule('PRE-' + prior, 'ipv4') }}
}
{% endfor %}
{% endif %}
+ chain VYOS_FRAG_MARK {
+ type filter hook prerouting priority -450; policy accept;
+ ip frag-off & 0x3fff != 0 meta mark set 0xffff1 return
+ }
+
{% if ipv4.name is vyos_defined %}
{% for name_text, conf in ipv4.name.items() %}
chain NAME_{{ name_text }} {
@@ -133,7 +135,7 @@ table ip vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule(name_text, 'ipv4') }}
+ {{ conf | nft_default_rule('NAM-' + name_text, 'ipv4') }}
}
{% endfor %}
{% endif %}
@@ -202,13 +204,13 @@ table ip6 vyos_filter {
{% endif %}
{% if conf.rule is vyos_defined %}
{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
- {{ rule_conf | nft_rule('FWD', prior, rule_id ,'ip6') }}
+ {{ rule_conf | nft_rule('FWD', prior, rule_id, 'ip6') }}
{% if rule_conf.recent is vyos_defined %}
{% set ns.sets = ns.sets + ['FWD_' + prior + '_' + rule_id] %}
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('FWD-filter', 'ipv6') }}
+ {{ conf | nft_default_rule('FWD-' + prior, 'ipv6') }}
}
{% endfor %}
{% endif %}
@@ -222,13 +224,13 @@ table ip6 vyos_filter {
{% endif %}
{% if conf.rule is vyos_defined %}
{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
- {{ rule_conf | nft_rule('INP', prior, rule_id ,'ip6') }}
+ {{ rule_conf | nft_rule('INP', prior, rule_id, 'ip6') }}
{% if rule_conf.recent is vyos_defined %}
{% set ns.sets = ns.sets + ['INP_' + prior + '_' + rule_id] %}
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('INP-filter', 'ipv6') }}
+ {{ conf | nft_default_rule('INP-' + prior, 'ipv6') }}
}
{% endfor %}
{% endif %}
@@ -237,22 +239,38 @@ table ip6 vyos_filter {
{% for prior, conf in ipv6.output.items() %}
chain VYOS_IPV6_OUTPUT_{{ prior }} {
type filter hook output priority {{ prior }}; policy accept;
-{% if global_options.state_policy is vyos_defined %}
+{% if global_options.state_policy is vyos_defined and prior == 'filter' %}
jump VYOS_STATE_POLICY6
{% endif %}
{% if conf.rule is vyos_defined %}
{% 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') }}
+ {{ 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] %}
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule('OUT-filter', 'ipv6') }}
+ {{ conf | nft_default_rule('OUT-' + prior, 'ipv6') }}
}
{% endfor %}
{% endif %}
+{% if ipv6.prerouting is vyos_defined %}
+{% for prior, conf in ipv6.prerouting.items() %}
+ chain VYOS_IPV6_PREROUTING_{{ prior }} {
+ type filter hook prerouting priority {{ prior }}; policy accept;
+{% if conf.rule is vyos_defined %}
+{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
+ {{ rule_conf | nft_rule('PRE', prior, rule_id, 'ip6') }}
+{% if rule_conf.recent is vyos_defined %}
+{% set ns.sets = ns.sets + ['PRE_' + prior + '_' + rule_id] %}
+{% endif %}
+{% endfor %}
+{% endif %}
+ {{ conf | nft_default_rule('PRE-' + prior, 'ipv6') }}
+ }
+{% endfor %}
+{% endif %}
chain VYOS_FRAG6_MARK {
type filter hook prerouting priority -450; policy accept;
exthdr frag exists meta mark set 0xffff1 return
@@ -269,7 +287,7 @@ table ip6 vyos_filter {
{% endif %}
{% endfor %}
{% endif %}
- {{ conf | nft_default_rule(name_text, 'ipv6') }}
+ {{ conf | nft_default_rule('NAM-' + name_text, 'ipv6') }}
}
{% endfor %}
{% endif %}
@@ -321,7 +339,111 @@ table ip6 vyos_filter {
delete table bridge vyos_filter
{% endif %}
table bridge vyos_filter {
-{{ bridge_tmpl.bridge(bridge) }}
+{% if bridge is vyos_defined %}
+{% if bridge.forward is vyos_defined %}
+{% for prior, conf in bridge.forward.items() %}
+ chain VYOS_FORWARD_{{ prior }} {
+ type filter hook forward priority {{ prior }}; policy accept;
+{% if global_options.state_policy is vyos_defined %}
+ jump VYOS_STATE_POLICY
+{% endif %}
+{% if conf.rule is vyos_defined %}
+{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
+ {{ rule_conf | nft_rule('FWD', prior, rule_id, 'bri') }}
+{% endfor %}
+{% endif %}
+ {{ conf | nft_default_rule('FWD-' + prior, 'bri') }}
+ }
+{% endfor %}
+{% endif %}
+
+{% if bridge.input is vyos_defined %}
+{% for prior, conf in bridge.input.items() %}
+ chain VYOS_INPUT_{{ prior }} {
+ type filter hook input priority {{ prior }}; policy accept;
+{% if global_options.state_policy is vyos_defined %}
+ jump VYOS_STATE_POLICY
+{% endif %}
+{% if conf.rule is vyos_defined %}
+{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
+ {{ rule_conf | nft_rule('INP', prior, rule_id, 'bri') }}
+{% endfor %}
+{% endif %}
+ {{ conf | nft_default_rule('INP-' + prior, 'bri') }}
+ }
+{% endfor %}
+{% endif %}
+
+{% if bridge.output is vyos_defined %}
+{% 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
+ ct state invalid ether type 0x8864 counter accept
+{% endif %}
+{% endif %}
+{% if global_options.state_policy is vyos_defined %}
+ jump VYOS_STATE_POLICY
+{% endif %}
+{% if conf.rule is vyos_defined %}
+{% 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, 'bri') }}
+{% endfor %}
+{% endif %}
+ {{ conf | nft_default_rule('OUT-' + prior, 'bri') }}
+ }
+{% endfor %}
+{% endif %}
+
+{% if bridge.prerouting is vyos_defined %}
+{% for prior, conf in bridge.prerouting.items() %}
+ chain VYOS_PREROUTING_{{ prior }} {
+ type filter hook prerouting priority {{ prior }}; policy accept;
+{% if conf.rule is vyos_defined %}
+{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
+ {{ rule_conf | nft_rule('PRE', prior, rule_id, 'bri') }}
+{% endfor %}
+{% endif %}
+ {{ conf | nft_default_rule('PRE-' + prior, 'bri') }}
+ }
+{% endfor %}
+{% endif %}
+
+{% if bridge.name is vyos_defined %}
+{% for name_text, conf in bridge.name.items() %}
+ chain NAME_{{ name_text }} {
+{% if conf.rule is vyos_defined %}
+{% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not vyos_defined %}
+ {{ rule_conf | nft_rule('NAM', name_text, rule_id, 'bri') }}
+{% if rule_conf.recent is vyos_defined %}
+{% set ns.sets = ns.sets + ['NAM_' + name_text + '_' + rule_id] %}
+{% endif %}
+{% endfor %}
+{% endif %}
+ {{ conf | nft_default_rule('NAM-' + name_text, 'bri') }}
+ }
+{% endfor %}
+{% endif %}
+
+{% endif %}
{{ group_tmpl.groups(group, False, False) }}
+{{ group_tmpl.groups(group, True, False) }}
+{% 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', bridge=True) }}
+{% endif %}
+{% if global_options.state_policy.invalid is vyos_defined %}
+ {{ 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', bridge=True) }}
+{% endif %}
+ return
+ }
+{% endif %}
}
diff --git a/data/templates/firewall/sysctl-firewall.conf.j2 b/data/templates/firewall/sysctl-firewall.conf.j2
new file mode 100644
index 000000000..6c33ffdc8
--- /dev/null
+++ b/data/templates/firewall/sysctl-firewall.conf.j2
@@ -0,0 +1,36 @@
+# Autogenerated by firewall.py
+
+# gloabl 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 }}
+net.ipv4.conf.*.accept_source_route = {{ 1 if global_options.ip_src_route == 'enable' else 0 }}
+net.ipv6.conf.*.accept_redirects = {{ 1 if global_options.ipv6_receive_redirects == 'enable' else 0 }}
+net.ipv6.conf.*.accept_source_route = {{ 0 if global_options.ipv6_src_route == 'enable' else -1 }}
+net.ipv4.conf.all.log_martians = {{ 1 if global_options.log_martians == 'enable' else 0 }}
+net.ipv4.conf.*.accept_redirects = {{ 1 if global_options.receive_redirects == 'enable' else 0 }}
+net.ipv4.conf.*.send_redirects = {{ 1 if global_options.send_redirects == 'enable' else 0 }}
+net.ipv4.tcp_syncookies = {{ 1 if global_options.syn_cookies == 'enable' else 0 }}
+net.ipv4.tcp_rfc1337 = {{ 1 if global_options.twa_hazards_protection == 'enable' else 0 }}
+
+{% if global_options.apply_to_bridged_traffic is vyos_defined %}
+net.bridge.bridge-nf-call-iptables = {{ 1 if global_options.apply_to_bridged_traffic.ipv4 is vyos_defined else 0 }}
+net.bridge.bridge-nf-call-ip6tables = {{ 1 if global_options.apply_to_bridged_traffic.ipv6 is vyos_defined else 0 }}
+{% else %}
+net.bridge.bridge-nf-call-iptables = 0
+net.bridge.bridge-nf-call-ip6tables = 0
+{% endif %}
+
+## Timeout values:
+net.netfilter.nf_conntrack_icmp_timeout = {{ global_options.timeout.icmp }}
+net.netfilter.nf_conntrack_generic_timeout = {{ global_options.timeout.other }}
+net.netfilter.nf_conntrack_tcp_timeout_close_wait = {{ global_options.timeout.tcp.close_wait }}
+net.netfilter.nf_conntrack_tcp_timeout_close = {{ global_options.timeout.tcp.close }}
+net.netfilter.nf_conntrack_tcp_timeout_established = {{ global_options.timeout.tcp.established }}
+net.netfilter.nf_conntrack_tcp_timeout_fin_wait = {{ global_options.timeout.tcp.fin_wait }}
+net.netfilter.nf_conntrack_tcp_timeout_last_ack = {{ global_options.timeout.tcp.last_ack }}
+net.netfilter.nf_conntrack_tcp_timeout_syn_recv = {{ global_options.timeout.tcp.syn_recv }}
+net.netfilter.nf_conntrack_tcp_timeout_syn_sent = {{ global_options.timeout.tcp.syn_sent }}
+net.netfilter.nf_conntrack_tcp_timeout_time_wait = {{ global_options.timeout.tcp.time_wait }}
+net.netfilter.nf_conntrack_udp_timeout = {{ global_options.timeout.udp.other }}
+net.netfilter.nf_conntrack_udp_timeout_stream = {{ global_options.timeout.udp.stream }}
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..3b462b4a9 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() %}
@@ -245,9 +251,11 @@
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 }}
{% if parameters.ebgp_requires_policy is vyos_defined %}
@@ -302,7 +310,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' %}
@@ -512,13 +522,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 %}
diff --git a/data/templates/frr/daemons.frr.tmpl b/data/templates/frr/daemons.frr.tmpl
index 339b4e52f..835dc382b 100644
--- a/data/templates/frr/daemons.frr.tmpl
+++ b/data/templates/frr/daemons.frr.tmpl
@@ -30,13 +30,13 @@ isisd=yes
pimd=no
pim6d=yes
ldpd=yes
-nhrpd=no
+nhrpd=yes
eigrpd=no
babeld=yes
sharpd=no
pbrd=no
bfdd=yes
-fabricd=no
+fabricd=yes
vrrpd=no
pathd=no
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/eigrpd.frr.j2 b/data/templates/frr/eigrpd.frr.j2
index 3038a0b1d..d16963a51 100644
--- a/data/templates/frr/eigrpd.frr.j2
+++ b/data/templates/frr/eigrpd.frr.j2
@@ -1,21 +1,31 @@
!
-router eigrp {{ local_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
+router eigrp {{ system_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
{% if maximum_paths is vyos_defined %}
-maximum-paths {{ maximum_paths }}
+ maximum-paths {{ maximum_paths }}
{% endif %}
{% if metric.weights is vyos_defined %}
-metric weights {{ metric.weights }}
+ metric weights {{ metric.weights }}
{% endif %}
{% if network is vyos_defined %}
{% for net in network %}
-network {{ net }}
+ network {{ net }}
+{% endfor %}
+{% endif %}
+{% if passive_interface is vyos_defined %}
+{% for interface in passive_interface %}
+ passive-interface {{ interface }}
{% endfor %}
{% endif %}
{% if redistribute is vyos_defined %}
{% for protocol in redistribute %}
-redistribute {{ protocol }}
+ redistribute {{ protocol }}
{% endfor %}
{% endif %}
+{% if router_id is vyos_defined %}
+ eigrp router-id {{ router_id }}
+{% endif %}
{% if variance is vyos_defined %}
-variance {{ variance }}
-{% endif %} \ No newline at end of file
+ variance {{ variance }}
+{% endif %}
+exit
+!
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
new file mode 100644
index 000000000..3a0646eb8
--- /dev/null
+++ b/data/templates/frr/fabricd.frr.j2
@@ -0,0 +1,73 @@
+!
+{% for name, router_config in domain.items() %}
+{% if router_config.interface is vyos_defined %}
+{% for iface, iface_config in router_config.interface.items() %}
+interface {{ iface }}
+{% if iface_config.address_family.ipv4 is vyos_defined %}
+ ip router openfabric {{ name }}
+{% endif %}
+{% if iface_config.address_family.ipv6 is vyos_defined %}
+ ipv6 router openfabric {{ name }}
+{% endif %}
+{% if iface_config.csnp_interval is vyos_defined %}
+ openfabric csnp-interval {{ iface_config.csnp_interval }}
+{% endif %}
+{% if iface_config.hello_interval is vyos_defined %}
+ openfabric hello-interval {{ iface_config.hello_interval }}
+{% endif %}
+{% if iface_config.hello_multiplier is vyos_defined %}
+ openfabric hello-multiplier {{ iface_config.hello_multiplier }}
+{% endif %}
+{% if iface_config.metric is vyos_defined %}
+ openfabric metric {{ iface_config.metric }}
+{% endif %}
+{% if iface_config.passive is vyos_defined or iface == 'lo' %}
+ openfabric passive
+{% endif %}
+{% if iface_config.password.md5 is vyos_defined %}
+ openfabric password md5 {{ iface_config.password.md5 }}
+{% elif iface_config.password.plaintext_password is vyos_defined %}
+ openfabric password clear {{ iface_config.password.plaintext_password }}
+{% endif %}
+{% if iface_config.psnp_interval is vyos_defined %}
+ openfabric psnp-interval {{ iface_config.psnp_interval }}
+{% endif %}
+exit
+!
+{% endfor %}
+{% endif %}
+router openfabric {{ name }}
+ net {{ net }}
+{% if router_config.domain_password.md5 is vyos_defined %}
+ domain-password md5 {{ router_config.domain_password.plaintext_password }}
+{% elif router_config.domain_password.plaintext_password is vyos_defined %}
+ domain-password clear {{ router_config.domain_password.plaintext_password }}
+{% endif %}
+{% if router_config.log_adjacency_changes is vyos_defined %}
+ log-adjacency-changes
+{% endif %}
+{% if router_config.set_overload_bit is vyos_defined %}
+ set-overload-bit
+{% endif %}
+{% if router_config.purge_originator is vyos_defined %}
+ purge-originator
+{% endif %}
+{% if router_config.fabric_tier is vyos_defined %}
+ fabric-tier {{ router_config.fabric_tier }}
+{% endif %}
+{% if router_config.lsp_gen_interval is vyos_defined %}
+ lsp-gen-interval {{ router_config.lsp_gen_interval }}
+{% endif %}
+{% if router_config.lsp_refresh_interval is vyos_defined %}
+ lsp-refresh-interval {{ router_config.lsp_refresh_interval }}
+{% endif %}
+{% if router_config.max_lsp_lifetime is vyos_defined %}
+ max-lsp-lifetime {{ router_config.max_lsp_lifetime }}
+{% endif %}
+{% if router_config.spf_interval is vyos_defined %}
+ spf-interval {{ router_config.spf_interval }}
+{% endif %}
+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/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..bc2c74b10 100644
--- a/data/templates/frr/ospfd.frr.j2
+++ b/data/templates/frr/ospfd.frr.j2
@@ -30,6 +30,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 %}
@@ -125,7 +128,7 @@ router ospf {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
{% endfor %}
{% 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 %}
@@ -233,6 +236,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 +256,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/rpki.frr.j2 b/data/templates/frr/rpki.frr.j2
index 59724102c..edf0ccaa2 100644
--- a/data/templates/frr/rpki.frr.j2
+++ b/data/templates/frr/rpki.frr.j2
@@ -5,9 +5,9 @@ rpki
{% for peer, peer_config in 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 %}
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..70a810f43 100644
--- a/data/templates/frr/zebra.route-map.frr.j2
+++ b/data/templates/frr/zebra.route-map.frr.j2
@@ -1,4 +1,6 @@
!
+{{ 'no ' if disable_forwarding is vyos_defined }}{{ afi }} forwarding
+!
{% 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..718d47d8f 100644
--- a/data/templates/frr/zebra.segment_routing.frr.j2
+++ b/data/templates/frr/zebra.segment_routing.frr.j2
@@ -11,6 +11,9 @@ segment-routing
{% if locator_config.behavior_usid is vyos_defined %}
behavior usid
{% endif %}
+{% if locator_config.format is vyos_defined %}
+ format {{ locator_config.format }}
+{% endif %}
exit
!
{% endfor %}
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/https/nginx.default.j2 b/data/templates/https/nginx.default.j2
index 4619361e5..51da46946 100644
--- a/data/templates/https/nginx.default.j2
+++ b/data/templates/https/nginx.default.j2
@@ -48,7 +48,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|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|docs|openapi.json|redoc|graphql) {
{% 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/suricata.j2 b/data/templates/ids/suricata.j2
new file mode 100644
index 000000000..d76994c47
--- /dev/null
+++ b/data/templates/ids/suricata.j2
@@ -0,0 +1,1280 @@
+%YAML 1.1
+---
+
+# Suricata configuration file. In addition to the comments describing all
+# options in this file, full documentation can be found at:
+# https://suricata.readthedocs.io/en/latest/configuration/suricata-yaml.html
+#
+# This configuration file generated by:
+# Suricata 6.0.10
+
+##
+## Step 1: Inform Suricata about your network
+##
+
+vars:
+ # more specific is better for alert accuracy and performance
+ address-groups:
+{% for (name, value) in suricata['address_group'] %}
+ {{ name }}: "[{{ value | join(',') }}]"
+{% endfor %}
+
+ port-groups:
+{% for (name, value) in suricata['port_group'] %}
+ {{ name }}: "[{{ value | join(',') }}]"
+{% endfor %}
+
+##
+## Step 2: Select outputs to enable
+##
+
+# The default logging directory. Any log or output file will be
+# placed here if it's not specified with a full path name. This can be
+# overridden with the -l command line parameter.
+default-log-dir: /var/log/suricata/
+
+# Configure the type of alert (and other) logging you would like.
+{% if suricata.log is vyos_defined %}
+outputs:
+{% if suricata.log.eve is vyos_defined %}
+ # Extensible Event Format (nicknamed EVE) event log in JSON format
+ - eve-log:
+ enabled: yes
+ filetype: {{ suricata.log.eve.filetype }} #regular|syslog|unix_dgram|unix_stream|redis
+ filename: {{ suricata.log.eve.filename }}
+
+ types:
+{% if suricata.log.eve.type is not vyos_defined or "alert" in suricata.log.eve.type %}
+ - alert:
+ tagged-packets: yes
+{% endif %}
+{% if "http" in suricata.log.eve.type %}
+ - http:
+ enabled: yes
+ extended: yes
+{% endif %}
+{% if "tls" in suricata.log.eve.type %}
+ - tls:
+ enabled: yes
+ extended: yes # enable this for extended logging information
+{% endif %}
+{% for protocol in suricata.log.eve.type %}
+{% if protocol not in ["alert","http","tls"] %}
+ - {{ protocol }}:
+ enabled: yes
+{% endif %}
+{% endfor %}
+{% endif %}
+{% endif %}
+
+##
+## Step 3: Configure common capture settings
+##
+## See "Advanced Capture Options" below for more options, including Netmap
+## and PF_RING.
+##
+
+# Linux high speed capture support
+af-packet:
+{% for interface in suricata.interface %}
+ - interface: {{ interface }}
+ # Default clusterid. AF_PACKET will load balance packets based on flow.
+ cluster-id: {{ 100 - loop.index }}
+ # Default AF_PACKET cluster type. AF_PACKET can load balance per flow or per hash.
+ # This is only supported for Linux kernel > 3.1
+ # possible value are:
+ # * cluster_flow: all packets of a given flow are sent to the same socket
+ # * cluster_cpu: all packets treated in kernel by a CPU are sent to the same socket
+ # * cluster_qm: all packets linked by network card to a RSS queue are sent to the same
+ # socket. Requires at least Linux 3.14.
+ # * cluster_ebpf: eBPF file load balancing. See doc/userguide/capture-hardware/ebpf-xdp.rst for
+ # more info.
+ # Recommended modes are cluster_flow on most boxes and cluster_cpu or cluster_qm on system
+ # with capture card using RSS (requires cpu affinity tuning and system IRQ tuning)
+ cluster-type: cluster_flow
+ # In some fragmentation cases, the hash can not be computed. If "defrag" is set
+ # to yes, the kernel will do the needed defragmentation before sending the packets.
+ defrag: yes
+{% endfor %}
+
+# Cross platform libpcap capture support
+pcap:
+{% for interface in suricata.interface %}
+ - interface: {{ interface }}
+{% endfor %}
+
+# Settings for reading pcap files
+pcap-file:
+ # Possible values are:
+ # - yes: checksum validation is forced
+ # - no: checksum validation is disabled
+ # - auto: Suricata uses a statistical approach to detect when
+ # checksum off-loading is used. (default)
+ # Warning: 'checksum-validation' must be set to yes to have checksum tested
+ checksum-checks: auto
+
+# See "Advanced Capture Options" below for more options, including Netmap
+# and PF_RING.
+
+
+##
+## Step 4: App Layer Protocol configuration
+##
+
+# Configure the app-layer parsers.
+#
+# The error-policy setting applies to all app-layer parsers. Values can be
+# "drop-flow", "pass-flow", "bypass", "drop-packet", "pass-packet", "reject" or
+# "ignore" (the default).
+#
+# The protocol's section details each protocol.
+#
+# The option "enabled" takes 3 values - "yes", "no", "detection-only".
+# "yes" enables both detection and the parser, "no" disables both, and
+# "detection-only" enables protocol detection only (parser disabled).
+app-layer:
+ # error-policy: ignore
+ protocols:
+ rfb:
+ enabled: yes
+ detection-ports:
+ dp: 5900, 5901, 5902, 5903, 5904, 5905, 5906, 5907, 5908, 5909
+ # MQTT, disabled by default.
+ mqtt:
+ enabled: yes
+ # max-msg-length: 1mb
+ # subscribe-topic-match-limit: 100
+ # unsubscribe-topic-match-limit: 100
+ # Maximum number of live MQTT transactions per flow
+ # max-tx: 4096
+ krb5:
+ enabled: yes
+ snmp:
+ enabled: yes
+ ikev2:
+ enabled: yes
+ tls:
+ enabled: yes
+ detection-ports:
+ dp: 443
+
+ # Generate JA3 fingerprint from client hello. If not specified it
+ # will be disabled by default, but enabled if rules require it.
+ #ja3-fingerprints: auto
+
+ # What to do when the encrypted communications start:
+ # - default: keep tracking TLS session, check for protocol anomalies,
+ # inspect tls_* keywords. Disables inspection of unmodified
+ # 'content' signatures.
+ # - bypass: stop processing this flow as much as possible. No further
+ # TLS parsing and inspection. Offload flow bypass to kernel
+ # or hardware if possible.
+ # - full: keep tracking and inspection as normal. Unmodified content
+ # keyword signatures are inspected as well.
+ #
+ # For best performance, select 'bypass'.
+ #
+ #encryption-handling: default
+
+ dcerpc:
+ enabled: yes
+ ftp:
+ enabled: yes
+ # memcap: 64mb
+ rdp:
+ enabled: yes
+ ssh:
+ enabled: yes
+ #hassh: yes
+ # HTTP2: Experimental HTTP 2 support. Disabled by default.
+ http2:
+ enabled: no
+ # use http keywords on HTTP2 traffic
+ http1-rules: no
+ smtp:
+ enabled: yes
+ raw-extraction: no
+ # Configure SMTP-MIME Decoder
+ mime:
+ # Decode MIME messages from SMTP transactions
+ # (may be resource intensive)
+ # This field supersedes all others because it turns the entire
+ # process on or off
+ decode-mime: yes
+
+ # Decode MIME entity bodies (ie. Base64, quoted-printable, etc.)
+ decode-base64: yes
+ decode-quoted-printable: yes
+
+ # Maximum bytes per header data value stored in the data structure
+ # (default is 2000)
+ header-value-depth: 2000
+
+ # Extract URLs and save in state data structure
+ extract-urls: yes
+ # Set to yes to compute the md5 of the mail body. You will then
+ # be able to journalize it.
+ body-md5: no
+ # Configure inspected-tracker for file_data keyword
+ inspected-tracker:
+ content-limit: 100000
+ content-inspect-min-size: 32768
+ content-inspect-window: 4096
+ imap:
+ enabled: detection-only
+ smb:
+ enabled: yes
+ detection-ports:
+ dp: 139, 445
+
+ # Stream reassembly size for SMB streams. By default track it completely.
+ #stream-depth: 0
+
+ nfs:
+ enabled: yes
+ tftp:
+ enabled: yes
+ dns:
+ tcp:
+ enabled: yes
+ detection-ports:
+ dp: 53
+ udp:
+ enabled: yes
+ detection-ports:
+ dp: 53
+ http:
+ enabled: yes
+ # memcap: Maximum memory capacity for HTTP
+ # Default is unlimited, values can be 64mb, e.g.
+
+ # default-config: Used when no server-config matches
+ # personality: List of personalities used by default
+ # request-body-limit: Limit reassembly of request body for inspection
+ # by http_client_body & pcre /P option.
+ # response-body-limit: Limit reassembly of response body for inspection
+ # by file_data, http_server_body & pcre /Q option.
+ #
+ # For advanced options, see the user guide
+
+
+ # server-config: List of server configurations to use if address matches
+ # address: List of IP addresses or networks for this block
+ # personality: List of personalities used by this block
+ #
+ # Then, all the fields from default-config can be overloaded
+ #
+ # Currently Available Personalities:
+ # Minimal, Generic, IDS (default), IIS_4_0, IIS_5_0, IIS_5_1, IIS_6_0,
+ # IIS_7_0, IIS_7_5, Apache_2
+ libhtp:
+ default-config:
+ personality: IDS
+
+ # Can be specified in kb, mb, gb. Just a number indicates
+ # it's in bytes.
+ request-body-limit: 100kb
+ response-body-limit: 100kb
+
+ # inspection limits
+ request-body-minimal-inspect-size: 32kb
+ request-body-inspect-window: 4kb
+ response-body-minimal-inspect-size: 40kb
+ response-body-inspect-window: 16kb
+
+ # response body decompression (0 disables)
+ response-body-decompress-layer-limit: 2
+
+ # auto will use http-body-inline mode in IPS mode, yes or no set it statically
+ http-body-inline: auto
+
+ # Decompress SWF files.
+ # Two types: 'deflate', 'lzma', 'both' will decompress deflate and lzma
+ # compress-depth:
+ # Specifies the maximum amount of data to decompress,
+ # set 0 for unlimited.
+ # decompress-depth:
+ # Specifies the maximum amount of decompressed data to obtain,
+ # set 0 for unlimited.
+ swf-decompression:
+ enabled: yes
+ type: both
+ compress-depth: 100kb
+ decompress-depth: 100kb
+
+ # Use a random value for inspection sizes around the specified value.
+ # This lowers the risk of some evasion techniques but could lead
+ # to detection change between runs. It is set to 'yes' by default.
+ #randomize-inspection-sizes: yes
+ # If "randomize-inspection-sizes" is active, the value of various
+ # inspection size will be chosen from the [1 - range%, 1 + range%]
+ # range
+ # Default value of "randomize-inspection-range" is 10.
+ #randomize-inspection-range: 10
+
+ # decoding
+ double-decode-path: no
+ double-decode-query: no
+
+ # Can enable LZMA decompression
+ #lzma-enabled: false
+ # Memory limit usage for LZMA decompression dictionary
+ # Data is decompressed until dictionary reaches this size
+ #lzma-memlimit: 1mb
+ # Maximum decompressed size with a compression ratio
+ # above 2048 (only LZMA can reach this ratio, deflate cannot)
+ #compression-bomb-limit: 1mb
+ # Maximum time spent decompressing a single transaction in usec
+ #decompression-time-limit: 100000
+
+ server-config:
+
+ #- apache:
+ # address: [192.168.1.0/24, 127.0.0.0/8, "::1"]
+ # personality: Apache_2
+ # # Can be specified in kb, mb, gb. Just a number indicates
+ # # it's in bytes.
+ # request-body-limit: 4096
+ # response-body-limit: 4096
+ # double-decode-path: no
+ # double-decode-query: no
+
+ #- iis7:
+ # address:
+ # - 192.168.0.0/24
+ # - 192.168.10.0/24
+ # personality: IIS_7_0
+ # # Can be specified in kb, mb, gb. Just a number indicates
+ # # it's in bytes.
+ # request-body-limit: 4096
+ # response-body-limit: 4096
+ # double-decode-path: no
+ # double-decode-query: no
+
+ # Note: Modbus probe parser is minimalist due to the limited usage in the field.
+ # Only Modbus message length (greater than Modbus header length)
+ # and protocol ID (equal to 0) are checked in probing parser
+ # It is important to enable detection port and define Modbus port
+ # to avoid false positives
+ modbus:
+ # How many unanswered Modbus requests are considered a flood.
+ # If the limit is reached, the app-layer-event:modbus.flooded; will match.
+ #request-flood: 500
+
+ enabled: no
+ detection-ports:
+ dp: 502
+ # According to MODBUS Messaging on TCP/IP Implementation Guide V1.0b, it
+ # is recommended to keep the TCP connection opened with a remote device
+ # and not to open and close it for each MODBUS/TCP transaction. In that
+ # case, it is important to set the depth of the stream reassembling as
+ # unlimited (stream.reassembly.depth: 0)
+
+ # Stream reassembly size for modbus. By default track it completely.
+ stream-depth: 0
+
+ # DNP3
+ dnp3:
+ enabled: no
+ detection-ports:
+ dp: 20000
+
+ # SCADA EtherNet/IP and CIP protocol support
+ enip:
+ enabled: no
+ detection-ports:
+ dp: 44818
+ sp: 44818
+
+ ntp:
+ enabled: yes
+
+ dhcp:
+ enabled: yes
+
+ sip:
+ enabled: yes
+
+# Limit for the maximum number of asn1 frames to decode (default 256)
+asn1-max-frames: 256
+
+# Datasets default settings
+# datasets:
+# # Default fallback memcap and hashsize values for datasets in case these
+# # were not explicitly defined.
+# defaults:
+# memcap: 100mb
+# hashsize: 2048
+
+##############################################################################
+##
+## Advanced settings below
+##
+##############################################################################
+
+##
+## Run Options
+##
+
+# Run Suricata with a specific user-id and group-id:
+#run-as:
+# user: suri
+# group: suri
+
+# Some logging modules will use that name in event as identifier. The default
+# value is the hostname
+#sensor-name: suricata
+
+# Default location of the pid file. The pid file is only used in
+# daemon mode (start Suricata with -D). If not running in daemon mode
+# the --pidfile command line option must be used to create a pid file.
+#pid-file: /var/run/suricata.pid
+
+# Daemon working directory
+# Suricata will change directory to this one if provided
+# Default: "/"
+#daemon-directory: "/"
+
+# Umask.
+# Suricata will use this umask if it is provided. By default it will use the
+# umask passed on by the shell.
+#umask: 022
+
+# Suricata core dump configuration. Limits the size of the core dump file to
+# approximately max-dump. The actual core dump size will be a multiple of the
+# page size. Core dumps that would be larger than max-dump are truncated. On
+# Linux, the actual core dump size may be a few pages larger than max-dump.
+# Setting max-dump to 0 disables core dumping.
+# Setting max-dump to 'unlimited' will give the full core dump file.
+# On 32-bit Linux, a max-dump value >= ULONG_MAX may cause the core dump size
+# to be 'unlimited'.
+
+coredump:
+ max-dump: unlimited
+
+# If the Suricata box is a router for the sniffed networks, set it to 'router'. If
+# it is a pure sniffing setup, set it to 'sniffer-only'.
+# If set to auto, the variable is internally switched to 'router' in IPS mode
+# and 'sniffer-only' in IDS mode.
+# This feature is currently only used by the reject* keywords.
+host-mode: auto
+
+# Number of packets preallocated per thread. The default is 1024. A higher number
+# will make sure each CPU will be more easily kept busy, but may negatively
+# impact caching.
+#max-pending-packets: 1024
+
+# Runmode the engine should use. Please check --list-runmodes to get the available
+# runmodes for each packet acquisition method. Default depends on selected capture
+# method. 'workers' generally gives best performance.
+#runmode: autofp
+
+# Specifies the kind of flow load balancer used by the flow pinned autofp mode.
+#
+# Supported schedulers are:
+#
+# hash - Flow assigned to threads using the 5-7 tuple hash.
+# ippair - Flow assigned to threads using addresses only.
+#
+#autofp-scheduler: hash
+
+# Preallocated size for each packet. Default is 1514 which is the classical
+# size for pcap on Ethernet. You should adjust this value to the highest
+# packet size (MTU + hardware header) on your system.
+#default-packet-size: 1514
+
+# Unix command socket that can be used to pass commands to Suricata.
+# An external tool can then connect to get information from Suricata
+# or trigger some modifications of the engine. Set enabled to yes
+# to activate the feature. In auto mode, the feature will only be
+# activated in live capture mode. You can use the filename variable to set
+# the file name of the socket.
+unix-command:
+ enabled: yes
+ filename: /run/suricata/suricata.socket
+
+# Magic file. The extension .mgc is added to the value here.
+#magic-file: /usr/share/file/magic
+#magic-file:
+
+# GeoIP2 database file. Specify path and filename of GeoIP2 database
+# if using rules with "geoip" rule option.
+#geoip-database: /usr/local/share/GeoLite2/GeoLite2-Country.mmdb
+
+legacy:
+ uricontent: enabled
+
+##
+## Detection settings
+##
+
+# Set the order of alerts based on actions
+# The default order is pass, drop, reject, alert
+# action-order:
+# - pass
+# - drop
+# - reject
+# - alert
+
+# Define maximum number of possible alerts that can be triggered for the same
+# packet. Default is 15
+#packet-alert-max: 15
+
+# IP Reputation
+#reputation-categories-file: /etc/suricata/iprep/categories.txt
+#default-reputation-path: /etc/suricata/iprep
+#reputation-files:
+# - reputation.list
+
+# When run with the option --engine-analysis, the engine will read each of
+# the parameters below, and print reports for each of the enabled sections
+# and exit. The reports are printed to a file in the default log dir
+# given by the parameter "default-log-dir", with engine reporting
+# subsection below printing reports in its own report file.
+engine-analysis:
+ # enables printing reports for fast-pattern for every rule.
+ rules-fast-pattern: yes
+ # enables printing reports for each rule
+ rules: yes
+
+#recursion and match limits for PCRE where supported
+pcre:
+ match-limit: 3500
+ match-limit-recursion: 1500
+
+##
+## Advanced Traffic Tracking and Reconstruction Settings
+##
+
+# Host specific policies for defragmentation and TCP stream
+# reassembly. The host OS lookup is done using a radix tree, just
+# like a routing table so the most specific entry matches.
+host-os-policy:
+ # Make the default policy windows.
+ windows: [0.0.0.0/0]
+ bsd: []
+ bsd-right: []
+ old-linux: []
+ linux: []
+ old-solaris: []
+ solaris: []
+ hpux10: []
+ hpux11: []
+ irix: []
+ macos: []
+ vista: []
+ windows2k3: []
+
+# Defrag settings:
+
+# The memcap-policy value can be "drop-flow", "pass-flow", "bypass",
+# "drop-packet", "pass-packet", "reject" or "ignore" (which is the default).
+defrag:
+ memcap: 32mb
+ # memcap-policy: ignore
+ hash-size: 65536
+ trackers: 65535 # number of defragmented flows to follow
+ max-frags: 65535 # number of fragments to keep (higher than trackers)
+ prealloc: yes
+ timeout: 60
+
+# Enable defrag per host settings
+# host-config:
+#
+# - dmz:
+# timeout: 30
+# address: [192.168.1.0/24, 127.0.0.0/8, 1.1.1.0/24, 2.2.2.0/24, "1.1.1.1", "2.2.2.2", "::1"]
+#
+# - lan:
+# timeout: 45
+# address:
+# - 192.168.0.0/24
+# - 192.168.10.0/24
+# - 172.16.14.0/24
+
+# Flow settings:
+# By default, the reserved memory (memcap) for flows is 32MB. This is the limit
+# for flow allocation inside the engine. You can change this value to allow
+# more memory usage for flows.
+# The hash-size determines the size of the hash used to identify flows inside
+# the engine, and by default the value is 65536.
+# At startup, the engine can preallocate a number of flows, to get better
+# performance. The number of flows preallocated is 10000 by default.
+# emergency-recovery is the percentage of flows that the engine needs to
+# prune before clearing the emergency state. The emergency state is activated
+# when the memcap limit is reached, allowing new flows to be created, but
+# pruning them with the emergency timeouts (they are defined below).
+# If the memcap is reached, the engine will try to prune flows
+# with the default timeouts. If it doesn't find a flow to prune, it will set
+# the emergency bit and it will try again with more aggressive timeouts.
+# If that doesn't work, then it will try to kill the oldest flows using
+# last time seen flows.
+# The memcap can be specified in kb, mb, gb. Just a number indicates it's
+# in bytes.
+# The memcap-policy can be "drop-flow", "pass-flow", "bypass", "drop-packet",
+# "pass-packet", "reject" or "ignore" (which is the default).
+
+flow:
+ memcap: 128mb
+ #memcap-policy: ignore
+ hash-size: 65536
+ prealloc: 10000
+ emergency-recovery: 30
+ #managers: 1 # default to one flow manager
+ #recyclers: 1 # default to one flow recycler thread
+
+# This option controls the use of VLAN ids in the flow (and defrag)
+# hashing. Normally this should be enabled, but in some (broken)
+# setups where both sides of a flow are not tagged with the same VLAN
+# tag, we can ignore the VLAN id's in the flow hashing.
+vlan:
+ use-for-tracking: true
+
+# Specific timeouts for flows. Here you can specify the timeouts that the
+# active flows will wait to transit from the current state to another, on each
+# protocol. The value of "new" determines the seconds to wait after a handshake or
+# stream startup before the engine frees the data of that flow it doesn't
+# change the state to established (usually if we don't receive more packets
+# of that flow). The value of "established" is the amount of
+# seconds that the engine will wait to free the flow if that time elapses
+# without receiving new packets or closing the connection. "closed" is the
+# amount of time to wait after a flow is closed (usually zero). "bypassed"
+# timeout controls locally bypassed flows. For these flows we don't do any other
+# tracking. If no packets have been seen after this timeout, the flow is discarded.
+#
+# There's an emergency mode that will become active under attack circumstances,
+# making the engine to check flow status faster. This configuration variables
+# use the prefix "emergency-" and work similar as the normal ones.
+# Some timeouts doesn't apply to all the protocols, like "closed", for udp and
+# icmp.
+
+flow-timeouts:
+
+ default:
+ new: 30
+ established: 300
+ closed: 0
+ bypassed: 100
+ emergency-new: 10
+ emergency-established: 100
+ emergency-closed: 0
+ emergency-bypassed: 50
+ tcp:
+ new: 60
+ established: 600
+ closed: 60
+ bypassed: 100
+ emergency-new: 5
+ emergency-established: 100
+ emergency-closed: 10
+ emergency-bypassed: 50
+ udp:
+ new: 30
+ established: 300
+ bypassed: 100
+ emergency-new: 10
+ emergency-established: 100
+ emergency-bypassed: 50
+ icmp:
+ new: 30
+ established: 300
+ bypassed: 100
+ emergency-new: 10
+ emergency-established: 100
+ emergency-bypassed: 50
+
+# Stream engine settings. Here the TCP stream tracking and reassembly
+# engine is configured.
+#
+# stream:
+# memcap: 64mb # Can be specified in kb, mb, gb. Just a
+# # number indicates it's in bytes.
+# memcap-policy: ignore # Can be "drop-flow", "pass-flow", "bypass",
+# # "drop-packet", "pass-packet", "reject" or
+# # "ignore" default is "ignore"
+# checksum-validation: yes # To validate the checksum of received
+# # packet. If csum validation is specified as
+# # "yes", then packets with invalid csum values will not
+# # be processed by the engine stream/app layer.
+# # Warning: locally generated traffic can be
+# # generated without checksum due to hardware offload
+# # of checksum. You can control the handling of checksum
+# # on a per-interface basis via the 'checksum-checks'
+# # option
+# prealloc-sessions: 2k # 2k sessions prealloc'd per stream thread
+# midstream: false # don't allow midstream session pickups
+# midstream-policy: ignore # Can be "drop-flow", "pass-flow", "bypass",
+# # "drop-packet", "pass-packet", "reject" or
+# # "ignore" default is "ignore"
+# async-oneside: false # don't enable async stream handling
+# inline: no # stream inline mode
+# drop-invalid: yes # in inline mode, drop packets that are invalid with regards to streaming engine
+# max-synack-queued: 5 # Max different SYN/ACKs to queue
+# bypass: no # Bypass packets when stream.reassembly.depth is reached.
+# # Warning: first side to reach this triggers
+# # the bypass.
+#
+# reassembly:
+# memcap: 256mb # Can be specified in kb, mb, gb. Just a number
+# # indicates it's in bytes.
+# memcap-policy: ignore # Can be "drop-flow", "pass-flow", "bypass",
+# # "drop-packet", "pass-packet", "reject" or
+# # "ignore" default is "ignore"
+# depth: 1mb # Can be specified in kb, mb, gb. Just a number
+# # indicates it's in bytes.
+# toserver-chunk-size: 2560 # inspect raw stream in chunks of at least
+# # this size. Can be specified in kb, mb,
+# # gb. Just a number indicates it's in bytes.
+# toclient-chunk-size: 2560 # inspect raw stream in chunks of at least
+# # this size. Can be specified in kb, mb,
+# # gb. Just a number indicates it's in bytes.
+# randomize-chunk-size: yes # Take a random value for chunk size around the specified value.
+# # This lowers the risk of some evasion techniques but could lead
+# # to detection change between runs. It is set to 'yes' by default.
+# randomize-chunk-range: 10 # If randomize-chunk-size is active, the value of chunk-size is
+# # a random value between (1 - randomize-chunk-range/100)*toserver-chunk-size
+# # and (1 + randomize-chunk-range/100)*toserver-chunk-size and the same
+# # calculation for toclient-chunk-size.
+# # Default value of randomize-chunk-range is 10.
+#
+# raw: yes # 'Raw' reassembly enabled or disabled.
+# # raw is for content inspection by detection
+# # engine.
+#
+# segment-prealloc: 2048 # number of segments preallocated per thread
+#
+# check-overlap-different-data: true|false
+# # check if a segment contains different data
+# # than what we've already seen for that
+# # position in the stream.
+# # This is enabled automatically if inline mode
+# # is used or when stream-event:reassembly_overlap_different_data;
+# # is used in a rule.
+#
+stream:
+ memcap: 64mb
+ #memcap-policy: ignore
+ checksum-validation: yes # reject incorrect csums
+ #midstream: false
+ #midstream-policy: ignore
+ inline: auto # auto will use inline mode in IPS mode, yes or no set it statically
+ reassembly:
+ memcap: 256mb
+ #memcap-policy: ignore
+ depth: 1mb # reassemble 1mb into a stream
+ toserver-chunk-size: 2560
+ toclient-chunk-size: 2560
+ randomize-chunk-size: yes
+ #randomize-chunk-range: 10
+ #raw: yes
+ #segment-prealloc: 2048
+ #check-overlap-different-data: true
+
+# Host table:
+#
+# Host table is used by the tagging and per host thresholding subsystems.
+#
+host:
+ hash-size: 4096
+ prealloc: 1000
+ memcap: 32mb
+
+# IP Pair table:
+#
+# Used by xbits 'ippair' tracking.
+#
+#ippair:
+# hash-size: 4096
+# prealloc: 1000
+# memcap: 32mb
+
+# Decoder settings
+
+decoder:
+ # Teredo decoder is known to not be completely accurate
+ # as it will sometimes detect non-teredo as teredo.
+ teredo:
+ enabled: true
+ # ports to look for Teredo. Max 4 ports. If no ports are given, or
+ # the value is set to 'any', Teredo detection runs on _all_ UDP packets.
+ ports: $TEREDO_PORTS # syntax: '[3544, 1234]' or '3533' or 'any'.
+
+ # VXLAN decoder is assigned to up to 4 UDP ports. By default only the
+ # IANA assigned port 4789 is enabled.
+ vxlan:
+ enabled: true
+ ports: $VXLAN_PORTS # syntax: '[8472, 4789]' or '4789'.
+
+ # VNTag decode support
+ vntag:
+ enabled: false
+
+ # Geneve decoder is assigned to up to 4 UDP ports. By default only the
+ # IANA assigned port 6081 is enabled.
+ geneve:
+ enabled: true
+ ports: $GENEVE_PORTS # syntax: '[6081, 1234]' or '6081'.
+
+ # maximum number of decoder layers for a packet
+ # max-layers: 16
+
+##
+## Performance tuning and profiling
+##
+
+# The detection engine builds internal groups of signatures. The engine
+# allows us to specify the profile to use for them, to manage memory in an
+# efficient way keeping good performance. For the profile keyword you
+# can use the words "low", "medium", "high" or "custom". If you use custom,
+# make sure to define the values in the "custom-values" section.
+# Usually you would prefer medium/high/low.
+#
+# "sgh mpm-context", indicates how the staging should allot mpm contexts for
+# the signature groups. "single" indicates the use of a single context for
+# all the signature group heads. "full" indicates a mpm-context for each
+# group head. "auto" lets the engine decide the distribution of contexts
+# based on the information the engine gathers on the patterns from each
+# group head.
+#
+# The option inspection-recursion-limit is used to limit the recursive calls
+# in the content inspection code. For certain payload-sig combinations, we
+# might end up taking too much time in the content inspection code.
+# If the argument specified is 0, the engine uses an internally defined
+# default limit. When a value is not specified, there are no limits on the recursion.
+detect:
+ profile: medium
+ custom-values:
+ toclient-groups: 3
+ toserver-groups: 25
+ sgh-mpm-context: auto
+ inspection-recursion-limit: 3000
+ # If set to yes, the loading of signatures will be made after the capture
+ # is started. This will limit the downtime in IPS mode.
+ #delayed-detect: yes
+
+ prefilter:
+ # default prefiltering setting. "mpm" only creates MPM/fast_pattern
+ # engines. "auto" also sets up prefilter engines for other keywords.
+ # Use --list-keywords=all to see which keywords support prefiltering.
+ default: mpm
+
+ # the grouping values above control how many groups are created per
+ # direction. Port whitelisting forces that port to get its own group.
+ # Very common ports will benefit, as well as ports with many expensive
+ # rules.
+ grouping:
+ #tcp-whitelist: 53, 80, 139, 443, 445, 1433, 3306, 3389, 6666, 6667, 8080
+ #udp-whitelist: 53, 135, 5060
+
+ profiling:
+ # Log the rules that made it past the prefilter stage, per packet
+ # default is off. The threshold setting determines how many rules
+ # must have made it past pre-filter for that rule to trigger the
+ # logging.
+ #inspect-logging-threshold: 200
+ grouping:
+ dump-to-disk: false
+ include-rules: false # very verbose
+ include-mpm-stats: false
+
+# Select the multi pattern algorithm you want to run for scan/search the
+# in the engine.
+#
+# The supported algorithms are:
+# "ac" - Aho-Corasick, default implementation
+# "ac-bs" - Aho-Corasick, reduced memory implementation
+# "ac-ks" - Aho-Corasick, "Ken Steele" variant
+# "hs" - Hyperscan, available when built with Hyperscan support
+#
+# The default mpm-algo value of "auto" will use "hs" if Hyperscan is
+# available, "ac" otherwise.
+#
+# The mpm you choose also decides the distribution of mpm contexts for
+# signature groups, specified by the conf - "detect.sgh-mpm-context".
+# Selecting "ac" as the mpm would require "detect.sgh-mpm-context"
+# to be set to "single", because of ac's memory requirements, unless the
+# ruleset is small enough to fit in memory, in which case one can
+# use "full" with "ac". The rest of the mpms can be run in "full" mode.
+
+mpm-algo: auto
+
+# Select the matching algorithm you want to use for single-pattern searches.
+#
+# Supported algorithms are "bm" (Boyer-Moore) and "hs" (Hyperscan, only
+# available if Suricata has been built with Hyperscan support).
+#
+# The default of "auto" will use "hs" if available, otherwise "bm".
+
+spm-algo: auto
+
+# Suricata is multi-threaded. Here the threading can be influenced.
+threading:
+ set-cpu-affinity: no
+ # Tune cpu affinity of threads. Each family of threads can be bound
+ # to specific CPUs.
+ #
+ # These 2 apply to the all runmodes:
+ # management-cpu-set is used for flow timeout handling, counters
+ # worker-cpu-set is used for 'worker' threads
+ #
+ # Additionally, for autofp these apply:
+ # receive-cpu-set is used for capture threads
+ # verdict-cpu-set is used for IPS verdict threads
+ #
+ cpu-affinity:
+ - management-cpu-set:
+ cpu: [ 0 ] # include only these CPUs in affinity settings
+ - receive-cpu-set:
+ cpu: [ 0 ] # include only these CPUs in affinity settings
+ - worker-cpu-set:
+ cpu: [ "all" ]
+ mode: "exclusive"
+ # Use explicitly 3 threads and don't compute number by using
+ # detect-thread-ratio variable:
+ # threads: 3
+ prio:
+ low: [ 0 ]
+ medium: [ "1-2" ]
+ high: [ 3 ]
+ default: "medium"
+ #- verdict-cpu-set:
+ # cpu: [ 0 ]
+ # prio:
+ # default: "high"
+ #
+ # By default Suricata creates one "detect" thread per available CPU/CPU core.
+ # This setting allows controlling this behaviour. A ratio setting of 2 will
+ # create 2 detect threads for each CPU/CPU core. So for a dual core CPU this
+ # will result in 4 detect threads. If values below 1 are used, less threads
+ # are created. So on a dual core CPU a setting of 0.5 results in 1 detect
+ # thread being created. Regardless of the setting at a minimum 1 detect
+ # thread will always be created.
+ #
+ detect-thread-ratio: 1.0
+ #
+ # By default, the per-thread stack size is left to its default setting. If
+ # the default thread stack size is too small, use the following configuration
+ # setting to change the size. Note that if any thread's stack size cannot be
+ # set to this value, a fatal error occurs.
+ #
+ # Generally, the per-thread stack-size should not exceed 8MB.
+ #stack-size: 8mb
+
+# Luajit has a strange memory requirement, its 'states' need to be in the
+# first 2G of the process' memory.
+#
+# 'luajit.states' is used to control how many states are preallocated.
+# State use: per detect script: 1 per detect thread. Per output script: 1 per
+# script.
+luajit:
+ states: 128
+
+# Profiling settings. Only effective if Suricata has been built with
+# the --enable-profiling configure flag.
+#
+profiling:
+ # Run profiling for every X-th packet. The default is 1, which means we
+ # profile every packet. If set to 1000, one packet is profiled for every
+ # 1000 received.
+ #sample-rate: 1000
+
+ # rule profiling
+ rules:
+
+ # Profiling can be disabled here, but it will still have a
+ # performance impact if compiled in.
+ enabled: yes
+ filename: rule_perf.log
+ append: yes
+
+ # Sort options: ticks, avgticks, checks, matches, maxticks
+ # If commented out all the sort options will be used.
+ #sort: avgticks
+
+ # Limit the number of sids for which stats are shown at exit (per sort).
+ limit: 10
+
+ # output to json
+ json: yes
+
+ # per keyword profiling
+ keywords:
+ enabled: yes
+ filename: keyword_perf.log
+ append: yes
+
+ prefilter:
+ enabled: yes
+ filename: prefilter_perf.log
+ append: yes
+
+ # per rulegroup profiling
+ rulegroups:
+ enabled: yes
+ filename: rule_group_perf.log
+ append: yes
+
+ # packet profiling
+ packets:
+
+ # Profiling can be disabled here, but it will still have a
+ # performance impact if compiled in.
+ enabled: yes
+ filename: packet_stats.log
+ append: yes
+
+ # per packet csv output
+ csv:
+
+ # Output can be disabled here, but it will still have a
+ # performance impact if compiled in.
+ enabled: no
+ filename: packet_stats.csv
+
+ # profiling of locking. Only available when Suricata was built with
+ # --enable-profiling-locks.
+ locks:
+ enabled: no
+ filename: lock_stats.log
+ append: yes
+
+ pcap-log:
+ enabled: no
+ filename: pcaplog_stats.log
+ append: yes
+
+##
+## Netfilter integration
+##
+
+# When running in NFQ inline mode, it is possible to use a simulated
+# non-terminal NFQUEUE verdict.
+# This permits sending all needed packet to Suricata via this rule:
+# iptables -I FORWARD -m mark ! --mark $MARK/$MASK -j NFQUEUE
+# And below, you can have your standard filtering ruleset. To activate
+# this mode, you need to set mode to 'repeat'
+# If you want a packet to be sent to another queue after an ACCEPT decision
+# set the mode to 'route' and set next-queue value.
+# On Linux >= 3.1, you can set batchcount to a value > 1 to improve performance
+# by processing several packets before sending a verdict (worker runmode only).
+# On Linux >= 3.6, you can set the fail-open option to yes to have the kernel
+# accept the packet if Suricata is not able to keep pace.
+# bypass mark and mask can be used to implement NFQ bypass. If bypass mark is
+# set then the NFQ bypass is activated. Suricata will set the bypass mark/mask
+# on packet of a flow that need to be bypassed. The Nefilter ruleset has to
+# directly accept all packets of a flow once a packet has been marked.
+nfq:
+# mode: accept
+# repeat-mark: 1
+# repeat-mask: 1
+# bypass-mark: 1
+# bypass-mask: 1
+# route-queue: 2
+# batchcount: 20
+# fail-open: yes
+
+#nflog support
+nflog:
+ # netlink multicast group
+ # (the same as the iptables --nflog-group param)
+ # Group 0 is used by the kernel, so you can't use it
+ - group: 2
+ # netlink buffer size
+ buffer-size: 18432
+ # put default value here
+ - group: default
+ # set number of packets to queue inside kernel
+ qthreshold: 1
+ # set the delay before flushing packet in the kernel's queue
+ qtimeout: 100
+ # netlink max buffer size
+ max-size: 20000
+
+##
+## Advanced Capture Options
+##
+
+# General settings affecting packet capture
+capture:
+ # disable NIC offloading. It's restored when Suricata exits.
+ # Enabled by default.
+ #disable-offloading: false
+ #
+ # disable checksum validation. Same as setting '-k none' on the
+ # commandline.
+ #checksum-validation: none
+
+# Netmap support
+#
+# Netmap operates with NIC directly in driver, so you need FreeBSD 11+ which has
+# built-in Netmap support or compile and install the Netmap module and appropriate
+# NIC driver for your Linux system.
+# To reach maximum throughput disable all receive-, segmentation-,
+# checksum- offloading on your NIC (using ethtool or similar).
+# Disabling TX checksum offloading is *required* for connecting OS endpoint
+# with NIC endpoint.
+# You can find more information at https://github.com/luigirizzo/netmap
+#
+netmap:
+ - interface: default
+
+# PF_RING configuration: for use with native PF_RING support
+# for more info see http://www.ntop.org/products/pf_ring/
+pfring:
+ - interface: default
+ #threads: 2
+
+# For FreeBSD ipfw(8) divert(4) support.
+# Please make sure you have ipfw_load="YES" and ipdivert_load="YES"
+# in /etc/loader.conf or kldload'ing the appropriate kernel modules.
+# Additionally, you need to have an ipfw rule for the engine to see
+# the packets from ipfw. For Example:
+#
+# ipfw add 100 divert 8000 ip from any to any
+#
+# N.B. This example uses "8000" -- this number must mach the values
+# you passed on the command line, i.e., -d 8000
+#
+ipfw:
+
+ # Reinject packets at the specified ipfw rule number. This config
+ # option is the ipfw rule number AT WHICH rule processing continues
+ # in the ipfw processing system after the engine has finished
+ # inspecting the packet for acceptance. If no rule number is specified,
+ # accepted packets are reinjected at the divert rule which they entered
+ # and IPFW rule processing continues. No check is done to verify
+ # this will rule makes sense so care must be taken to avoid loops in ipfw.
+ #
+ ## The following example tells the engine to reinject packets
+ # back into the ipfw firewall AT rule number 5500:
+ #
+ # ipfw-reinjection-rule-number: 5500
+
+
+napatech:
+ # When use_all_streams is set to "yes" the initialization code will query
+ # the Napatech service for all configured streams and listen on all of them.
+ # When set to "no" the streams config array will be used.
+ #
+ # This option necessitates running the appropriate NTPL commands to create
+ # the desired streams prior to running Suricata.
+ #use-all-streams: no
+
+ # The streams to listen on when auto-config is disabled or when and threading
+ # cpu-affinity is disabled. This can be either:
+ # an individual stream (e.g. streams: [0])
+ # or
+ # a range of streams (e.g. streams: ["0-3"])
+ #
+ streams: ["0-3"]
+
+ # Stream stats can be enabled to provide fine grain packet and byte counters
+ # for each thread/stream that is configured.
+ #
+ enable-stream-stats: no
+
+ # When auto-config is enabled the streams will be created and assigned
+ # automatically to the NUMA node where the thread resides. If cpu-affinity
+ # is enabled in the threading section. Then the streams will be created
+ # according to the number of worker threads specified in the worker-cpu-set.
+ # Otherwise, the streams array is used to define the streams.
+ #
+ # This option is intended primarily to support legacy configurations.
+ #
+ # This option cannot be used simultaneously with either "use-all-streams"
+ # or "hardware-bypass".
+ #
+ auto-config: yes
+
+ # Enable hardware level flow bypass.
+ #
+ hardware-bypass: yes
+
+ # Enable inline operation. When enabled traffic arriving on a given port is
+ # automatically forwarded out its peer port after analysis by Suricata.
+ #
+ inline: no
+
+ # Ports indicates which Napatech ports are to be used in auto-config mode.
+ # these are the port IDs of the ports that will be merged prior to the
+ # traffic being distributed to the streams.
+ #
+ # When hardware-bypass is enabled the ports must be configured as a segment.
+ # specify the port(s) on which upstream and downstream traffic will arrive.
+ # This information is necessary for the hardware to properly process flows.
+ #
+ # When using a tap configuration one of the ports will receive inbound traffic
+ # for the network and the other will receive outbound traffic. The two ports on a
+ # given segment must reside on the same network adapter.
+ #
+ # When using a SPAN-port configuration the upstream and downstream traffic
+ # arrives on a single port. This is configured by setting the two sides of the
+ # segment to reference the same port. (e.g. 0-0 to configure a SPAN port on
+ # port 0).
+ #
+ # port segments are specified in the form:
+ # ports: [0-1,2-3,4-5,6-6,7-7]
+ #
+ # For legacy systems when hardware-bypass is disabled this can be specified in any
+ # of the following ways:
+ #
+ # a list of individual ports (e.g. ports: [0,1,2,3])
+ #
+ # a range of ports (e.g. ports: [0-3])
+ #
+ # "all" to indicate that all ports are to be merged together
+ # (e.g. ports: [all])
+ #
+ # This parameter has no effect if auto-config is disabled.
+ #
+ ports: [0-1,2-3]
+
+ # When auto-config is enabled the hashmode specifies the algorithm for
+ # determining to which stream a given packet is to be delivered.
+ # This can be any valid Napatech NTPL hashmode command.
+ #
+ # The most common hashmode commands are: hash2tuple, hash2tuplesorted,
+ # hash5tuple, hash5tuplesorted and roundrobin.
+ #
+ # See Napatech NTPL documentation other hashmodes and details on their use.
+ #
+ # This parameter has no effect if auto-config is disabled.
+ #
+ hashmode: hash5tuplesorted
+
+##
+## Configure Suricata to load Suricata-Update managed rules.
+##
+
+# As VyOS leverages suricata-update, the default rule path points to the
+# generated rules instead of the built-in rules.
+#
+# default-rule-path: /etc/suricata/rules
+default-rule-path: /var/lib/suricata/rules
+
+rule-files:
+ - suricata.rules
+
+##
+## Auxiliary configuration files.
+##
+
+# As VyOS leverages suricata-update, the classification file points to the
+# generated classification instead of the built-in one.
+#
+# classification-file: /etc/suricata/classification.config
+classification-file: /var/lib/suricata/rules/classification.config
+reference-config-file: /etc/suricata/reference.config
+# threshold-file: /etc/suricata/threshold.config
+
+##
+## Include other configs
+##
+
+# Includes: Files included here will be handled as if they were in-lined
+# in this configuration file. Files with relative pathnames will be
+# searched for in the same directory as this configuration file. You may
+# use absolute pathnames too.
+# You can specify more than 2 configuration files, if needed.
+#include: include1.yaml
+#include: include2.yaml
diff --git a/data/templates/ids/suricata_logrotate.j2 b/data/templates/ids/suricata_logrotate.j2
new file mode 100644
index 000000000..62773fc68
--- /dev/null
+++ b/data/templates/ids/suricata_logrotate.j2
@@ -0,0 +1,17 @@
+{% for filename in [(log.eve.filename | default("eve.json"))] %}
+{{ filename if filename.startswith("/") else ("/var/log/suricata/" + filename) }}
+{% endfor %}{
+ weekly
+ dateext
+ dateformat _%Y-%m-%d_%H-%M-%S
+ maxsize 10M
+ rotate 10
+ missingok
+ nocompress
+ nocreate
+ nomail
+ sharedscripts
+ postrotate
+ /bin/kill -HUP `cat /run/suricata/suricata.pid 2>/dev/null` 2>/dev/null || true
+ endscript
+}
diff --git a/data/templates/ipsec/swanctl.conf.j2 b/data/templates/ipsec/swanctl.conf.j2
index d44d0f5e4..64e7ea860 100644
--- a/data/templates/ipsec/swanctl.conf.j2
+++ b/data/templates/ipsec/swanctl.conf.j2
@@ -31,6 +31,8 @@ pools {
{{ pool }} {
{% if pool_config.prefix is vyos_defined %}
addrs = {{ pool_config.prefix }}
+{% elif pool_config.range is vyos_defined %}
+ addrs = {{ pool_config.range.start }}-{{ pool_config.range.stop }}
{% endif %}
{% if pool_config.name_server is vyos_defined %}
dns = {{ pool_config.name_server | join(',') }}
@@ -85,7 +87,11 @@ 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('plaintext') %}
secret = "{{ psk_config.secret }}"
+{% endif %}
}
{% endfor %}
{% endif %}
diff --git a/data/templates/ipsec/swanctl/profile.j2 b/data/templates/ipsec/swanctl/profile.j2
index 8519a84f8..6a04b038a 100644
--- a/data/templates/ipsec/swanctl/profile.j2
+++ b/data/templates/ipsec/swanctl/profile.j2
@@ -22,16 +22,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 e384ae972..c79f292b4 100644
--- a/data/templates/ipsec/swanctl/remote_access.j2
+++ b/data/templates/ipsec/swanctl/remote_access.j2
@@ -46,7 +46,7 @@
{% endif %}
}
children {
- ikev2-vpn {
+ {{ name }}-client {
esp_proposals = {{ esp | get_esp_ike_cipher(ike) | join(',') }}
{% if esp.life_bytes is vyos_defined %}
life_bytes = {{ esp.life_bytes }}
@@ -69,6 +69,13 @@
{% 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 '' %}
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. #}
+{# Thus we simply shift the key by one to also support a vti0 interface #}
+{% set if_id = rw_conf.bind | replace('vti', '') | int + 1 %}
+ if_id_in = {{ if_id }}
+ if_id_out = {{ if_id }}
+{% 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..70ea5d2b0 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
@@ -93,6 +94,11 @@ 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 }}
@@ -129,6 +135,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 %}
diff --git a/data/templates/load-balancing/nftables-wlb.j2 b/data/templates/load-balancing/nftables-wlb.j2
new file mode 100644
index 000000000..b3d7c3376
--- /dev/null
+++ b/data/templates/load-balancing/nftables-wlb.j2
@@ -0,0 +1,64 @@
+#!/usr/sbin/nft -f
+
+{% 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 }} 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 %}
+}
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/default_motd.j2 b/data/templates/login/default_motd.j2
index 543c6f8e0..0d52092f8 100644
--- a/data/templates/login/default_motd.j2
+++ b/data/templates/login/default_motd.j2
@@ -4,6 +4,9 @@ Welcome to VyOS!
. VyOS {{ version_data.version }}
└ ──┘ {{ version_data.release_train }}
+{% if version_data.lts_build %}
+ * Support portal: {{ version_data.support_url }}
+{% endif %}
* Documentation: {{ version_data.documentation_url }}
* Project news: {{ version_data.project_news_url }}
* Bug reports: {{ version_data.bugtracker_url }}
diff --git a/data/templates/login/motd_vyos_nonproduction.j2 b/data/templates/login/motd_vyos_nonproduction.j2
new file mode 100644
index 000000000..3f10423ff
--- /dev/null
+++ b/data/templates/login/motd_vyos_nonproduction.j2
@@ -0,0 +1,4 @@
+
+---
+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/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/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/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 236584387..be811f45e 100644
--- a/data/templates/openvpn/server.conf.j2
+++ b/data/templates/openvpn/server.conf.j2
@@ -11,11 +11,11 @@ dev-type {{ device_type }}
dev {{ ifname }}
persist-key
{% if protocol is vyos_defined('tcp-active') %}
-proto tcp-client
+proto tcp{{ protocol_modifier }}-client
{% elif protocol is vyos_defined('tcp-passive') %}
-proto tcp-server
+proto tcp{{ protocol_modifier }}-server
{% else %}
-proto udp
+proto udp{{ protocol_modifier }}
{% endif %}
{% if local_host is vyos_defined %}
local {{ local_host }}
@@ -63,6 +63,9 @@ nobind
#
# OpenVPN Server mode
#
+{% if ip_version is vyos_defined('ipv6') %}
+bind ipv6only
+{% endif %}
mode server
tls-server
{% if server is vyos_defined %}
@@ -131,6 +134,9 @@ plugin "{{ plugin_dir }}/openvpn-otp.so" "otp_secrets=/config/auth/openvpn/{{ if
#
# OpenVPN site-2-site mode
#
+{% if ip_version is vyos_defined('ipv6') %}
+bind ipv6only
+{% endif %}
ping {{ keep_alive.interval }}
ping-restart {{ keep_alive.failure_count }}
@@ -207,19 +213,12 @@ tls-server
{% if encryption is vyos_defined %}
{% if encryption.cipher is vyos_defined %}
cipher {{ encryption.cipher | openvpn_cipher }}
-{% if encryption.cipher is vyos_defined('bf128') %}
-keysize 128
-{% elif encryption.cipher is vyos_defined('bf256') %}
-keysize 256
-{% endif %}
{% endif %}
-{% if encryption.ncp_ciphers is vyos_defined %}
-data-ciphers {{ encryption.ncp_ciphers | openvpn_ncp_ciphers }}
+{% if encryption.data_ciphers is vyos_defined %}
+data-ciphers {{ encryption.data_ciphers | openvpn_data_ciphers }}
{% endif %}
{% endif %}
-# https://vyos.dev/T5027
-# Required to support BF-CBC (default ciphername when none given)
-providers legacy default
+providers default
{% if hash is vyos_defined %}
auth {{ hash }}
diff --git a/data/templates/pmacct/uacctd.conf.j2 b/data/templates/pmacct/uacctd.conf.j2
index aae0a0619..d2de80df4 100644
--- a/data/templates/pmacct/uacctd.conf.j2
+++ b/data/templates/pmacct/uacctd.conf.j2
@@ -25,12 +25,6 @@ imt_mem_pools_number: 169
{% 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 %}
@@ -61,20 +55,3 @@ nfprobe_timeouts[{{ nf_server_key }}]: expint={{ netflow.timeout.expiry_interval
{% 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/prometheus/blackbox_exporter.service.j2 b/data/templates/prometheus/blackbox_exporter.service.j2
new file mode 100644
index 000000000..e93030246
--- /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 }}:{{ 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..c3892e42b
--- /dev/null
+++ b/data/templates/prometheus/frr_exporter.service.j2
@@ -0,0 +1,20 @@
+{% 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 \
+{% if listen_address is vyos_defined %}
+{% for address in listen_address %}
+ --web.listen-address={{ address }}:{{ port }}
+{% endfor %}
+{% else %}
+ --web.listen-address=:{{ port }}
+{% endif %}
+[Install]
+WantedBy=multi-user.target
diff --git a/data/templates/prometheus/node_exporter.service.j2 b/data/templates/prometheus/node_exporter.service.j2
new file mode 100644
index 000000000..135439bd6
--- /dev/null
+++ b/data/templates/prometheus/node_exporter.service.j2
@@ -0,0 +1,25 @@
+{% set vrf_command = 'ip vrf exec ' ~ vrf ~ ' runuser -u node_exporter -- ' if vrf is vyos_defined else '' %}
+[Unit]
+Description=Node Exporter
+Documentation=https://github.com/prometheus/node_exporter
+After=network.target
+
+[Service]
+{% if vrf is not vyos_defined %}
+User=node_exporter
+{% endif %}
+ExecStart={{ vrf_command }}/usr/sbin/node_exporter \
+{% if listen_address is vyos_defined %}
+{% for address in listen_address %}
+ --web.listen-address={{ address }}:{{ port }}
+{% endfor %}
+{% else %}
+ --web.listen-address=:{{ port }}
+{% endif %}
+{% if collectors is vyos_defined %}
+{% if collectors.textfile is vyos_defined %}
+ --collector.textfile.directory=/run/node_exporter/collector
+{% endif %}
+{% endif %}
+[Install]
+WantedBy=multi-user.target
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 7fd592d1f..c6eb6430c 100644
--- a/data/templates/rsyslog/rsyslog.conf.j2
+++ b/data/templates/rsyslog/rsyslog.conf.j2
@@ -1,80 +1,122 @@
### 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 %}
-{% endif %}
-{% if global.preserve_fqdn is vyos_defined %}
-$PreserveFQDN on
-{% endif %}
+#### MODULES ####
+# Load input modules for local logging and kernel logging
-{% if global.local_host_name is vyos_defined %}
-$LocalHostName {{ global.local_host_name }}
-{% endif %}
+# 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
+module(load="imklog") # provides kernel logging support
-# 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
+# Import logs from journald
+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 %}
+# Load the immark module for periodic --MARK-- message capability
+module(load="immark" interval="{{ marker.interval }}")
+{% endif %}
+{% 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 %}
-{% 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 %}
+{% set tmp = [] %}
+{% if local.facility is vyos_defined %}
+{% for facility, facility_options in local.facility.items() %}
+{% set _ = tmp.append(facility.replace('all', '*') ~ "." ~ facility_options.level.replace('all', 'debug')) %}
+{% endfor %}
+if prifilt("{{ tmp | join(',') }}") then {
+ action(
+ type="omfile"
+ file="/var/log/messages"
+ rotation.sizeLimit="524288" # 512Kib - maximum filesize before rotation
+ rotation.sizeLimitCommand="/usr/sbin/logrotate {{ logrotate }}"
+ )
+}
+{% endif %}
{% 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 console.facility is vyos_defined %}
+{% for facility, facility_options in console.facility.items() %}
+{% set _ = tmp.append(facility.replace('all', '*') ~ "." ~ facility_options.level.replace('all', 'debug')) %}
+{% endfor %}
+if prifilt("{{ tmp | join(',') }}") then {
+ action(type="omfile" file="/dev/console")
+}
+{% endif %}
{% endif %}
-{% if host is vyos_defined %}
-# Remote logging
-{% for host_name, host_options in host.items() %}
+#### REMOTE LOGGING ####
+{% if remote is vyos_defined %}
+{% for remote_name, remote_options in remote.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', '*')) %}
+{% if remote_options.facility is vyos_defined %}
+{% for facility, facility_options in remote_options.facility.items() %}
+{% set _ = tmp.append(facility.replace('all', '*') ~ "." ~ facility_options.level.replace('all', 'debug')) %}
{% 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 }}
+{% set _ = tmp.sort() %}
+# Remote syslog to {{ remote_name }}
+if prifilt("{{ tmp | join(',') }}") then {
+ action(
+ type="omfwd"
+ # Remote syslog server where we send our logs to
+ target="{{ remote_name | bracketize_ipv6 }}"
+ # Port on the remote syslog server
+ port="{{ remote_options.port }}"
+ protocol="{{ remote_options.protocol }}"
+{% if remote_options.format.include_timezone is vyos_defined %}
+ template="SyslogProtocol23Format"
{% endif %}
-{% else %}
-{{ tmp | join(';') }} @{{ host_name | bracketize_ipv6 }}:{{ host_options.port }}{{ ';RSYSLOG_SyslogProtocol23Format' if host_options.format.include_timezone is vyos_defined }}
+ TCP_Framing="{{ 'octed-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 %}
+{% if remote_options.vrf is vyos_defined %}
+ Device="{{ remote_options.vrf }}"
+{% 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..6a1ba2956 100644
--- a/data/templates/sflow/hsflowd.conf.j2
+++ b/data/templates/sflow/hsflowd.conf.j2
@@ -25,6 +25,9 @@ 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 %}
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/sshd_config.j2 b/data/templates/ssh/sshd_config.j2
index 2cf0494c4..7e44efae8 100644
--- a/data/templates/ssh/sshd_config.j2
+++ b/data/templates/ssh/sshd_config.j2
@@ -110,3 +110,7 @@ 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_key is vyos_defined %}
+TrustedUserCAKeys /etc/ssh/trusted_user_ca_key
+{% endif %}
diff --git a/data/templates/stunnel/stunnel_config.j2 b/data/templates/stunnel/stunnel_config.j2
new file mode 100644
index 000000000..52c289fa9
--- /dev/null
+++ b/data/templates/stunnel/stunnel_config.j2
@@ -0,0 +1,118 @@
+; Autogenerated by service_stunnel.py
+
+; Example https://www.stunnel.org/config_unix.html#
+; **************************************************************************
+; * Global options *
+; **************************************************************************
+
+; PID file is created inside the chroot jail (if enabled)
+pid = {{ config_file | replace('.conf', '.pid') }}
+
+; Debugging stuff (may be useful for troubleshooting)
+;foreground = yes
+
+{% if log is vyos_defined %}
+debug = {{ log.level }}
+{% endif %}
+
+;output = /usr/local/var/log/stunnel.log
+
+
+; **************************************************************************
+; * Service definitions *
+; **************************************************************************
+
+; ***************************************** Client mode services ***********
+
+{% if client is vyos_defined %}
+{% for name, config in client.items() %}
+[{{ name }}]
+client = yes
+{% if config.listen.address is vyos_defined %}
+accept = {{ config.listen.address }}:{{ config.listen.port }}
+{% else %}
+accept = {{ config.listen.port }}
+{% endif %}
+{% if config.connect is vyos_defined %}
+{% if config.connect.address is vyos_defined %}
+connect = {{ config.connect.address }}:{{ config.connect.port }}
+{% else %}
+connect = {{ config.connect.port }}
+{% endif %}
+{% endif %}
+{% if config.protocol is vyos_defined %}
+protocol = {{ config.protocol }}
+{% endif %}
+{% if config.options is vyos_defined %}
+{% if config.options.authentication is vyos_defined %}
+protocolAuthentication = {{ config.options.authentication }}
+{% endif %}
+{% if config.options.domain is vyos_defined %}
+protocolDomain = {{ config.options.domain }}
+{% endif %}
+{% if config.options.host is vyos_defined %}
+protocolHost = {{ config.options.host.address }}:{{ config.options.host.port }}
+{% endif %}
+{% if config.options.password is vyos_defined %}
+protocolPassword = {{ config.options.password }}
+{% endif %}
+{% if config.options.username is vyos_defined %}
+protocolUsername = {{ config.options.username }}
+{% endif %}
+{% endif %}
+{% if config.ssl.ca_path is vyos_defined %}
+CApath = {{ config.ssl.ca_path }}
+{% endif %}
+{% if config.ssl.ca_file is vyos_defined %}
+CAfile = {{ config.ssl.ca_file }}
+{% endif %}
+{% if config.ssl.cert is vyos_defined %}
+cert = {{ config.ssl.cert }}
+{% endif %}
+{% if config.ssl.cert_key is vyos_defined %}
+key = {{ config.ssl.cert_key }}
+{% endif %}
+{% if config.psk.file is vyos_defined %}
+PSKsecrets = {{ config.psk.file }}
+{% endif %}
+{% endfor %}
+{% endif %}
+
+
+; ***************************************** Server mode services ***********
+
+{% if server is vyos_defined %}
+{% for name, config in server.items() %}
+[{{ name }}]
+{% if config.listen.address is vyos_defined %}
+accept = {{ config.listen.address }}:{{ config.listen.port }}
+{% else %}
+accept = {{ config.listen.port }}
+{% endif %}
+{% if config.connect is vyos_defined %}
+{% if config.connect.address is vyos_defined %}
+connect = {{ config.connect.address }}:{{ config.connect.port }}
+{% else %}
+connect = {{ config.connect.port }}
+{% endif %}
+{% endif %}
+{% if config.protocol is vyos_defined %}
+protocol = {{ config.protocol }}
+{% endif %}
+{% if config.ssl.ca_path is vyos_defined %}
+CApath = {{ config.ssl.ca_path }}
+{% endif %}
+{% if config.ssl.ca_file is vyos_defined %}
+CAfile = {{ config.ssl.ca_file }}
+{% endif %}
+{% if config.ssl.cert is vyos_defined %}
+cert = {{ config.ssl.cert }}
+{% endif %}
+{% if config.ssl.cert_key is vyos_defined %}
+key = {{ config.ssl.cert_key }}
+{% endif %}
+{% if config.psk.file is vyos_defined %}
+PSKsecrets = {{ config.psk.file }}
+{% endif %}
+{% endfor %}
+{% endif %}
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..043fc6878 100644
--- a/data/templates/telegraf/telegraf.j2
+++ b/data/templates/telegraf/telegraf.j2
@@ -52,7 +52,7 @@
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/wifi/wpa_supplicant.conf.j2 b/data/templates/wifi/wpa_supplicant.conf.j2
index ac857a04a..04088e1ad 100644
--- a/data/templates/wifi/wpa_supplicant.conf.j2
+++ b/data/templates/wifi/wpa_supplicant.conf.j2
@@ -61,6 +61,8 @@ network={
# If not set, this defaults to: WPA-PSK WPA-EAP
{% if security.wpa.mode is vyos_defined('wpa3') %}
key_mgmt=SAE
+{% elif security.wpa.username is vyos_defined %}
+ key_mgmt=WPA-EAP WPA-EAP-SHA256
{% else %}
key_mgmt=WPA-PSK WPA-PSK-SHA256
{% endif %}
@@ -76,8 +78,18 @@ network={
# from ASCII passphrase. This process uses lot of CPU and wpa_supplicant
# startup and reconfiguration time can be optimized by generating the PSK only
# only when the passphrase or SSID has actually changed.
+{% if security.wpa.username is vyos_defined %}
+ identity="{{ security.wpa.username }}"
+ password="{{ security.wpa.passphrase }}"
+ phase2="auth=MSCHAPV2"
+ eap=PEAP
+{% elif security.wpa.username is not vyos_defined %}
psk="{{ security.wpa.passphrase }}"
-{% else %}
+{% else %}
key_mgmt=NONE
+{% endif %}
+{% endif %}
+{% if bssid is vyos_defined %}
+ bssid={{ bssid }}
{% endif %}
}
diff --git a/data/templates/zabbix-agent/10-override.conf.j2 b/data/templates/zabbix-agent/10-override.conf.j2
index 7c296e8fd..f6bd6500d 100644
--- a/data/templates/zabbix-agent/10-override.conf.j2
+++ b/data/templates/zabbix-agent/10-override.conf.j2
@@ -1,3 +1,4 @@
+{% set zabbix_command = 'ip vrf exec ' ~ vrf ~ ' ' if vrf is vyos_defined else '' %}
[Unit]
After=
After=vyos-router.service
@@ -5,9 +6,11 @@ ConditionPathExists=
ConditionPathExists=/run/zabbix/zabbix-agent2.conf
[Service]
+User=
+User=root
EnvironmentFile=
ExecStart=
-ExecStart=/usr/sbin/zabbix_agent2 --config /run/zabbix/zabbix-agent2.conf --foreground
+ExecStart={{ zabbix_command }}/usr/sbin/zabbix_agent2 --config /run/zabbix/zabbix-agent2.conf --foreground
WorkingDirectory=
WorkingDirectory=/run/zabbix
Restart=always
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 %}
+