diff --git a/data/configd-include.json b/data/configd-include.json index 6893aaa86..ee4cb0d42 100644 --- a/data/configd-include.json +++ b/data/configd-include.json @@ -1,73 +1,74 @@ [ "bcast_relay.py", "conntrack.py", "conntrack_sync.py", "dhcp_relay.py", "dhcpv6_relay.py", "dns_forwarding.py", "dynamic_dns.py", +"flow_accounting_conf.py", "host_name.py", "https.py", "igmp_proxy.py", "intel_qat.py", "interfaces-bonding.py", "interfaces-bridge.py", "interfaces-dummy.py", "interfaces-ethernet.py", "interfaces-geneve.py", "interfaces-l2tpv3.py", "interfaces-loopback.py", "interfaces-macsec.py", "interfaces-openvpn.py", "interfaces-pppoe.py", "interfaces-pseudo-ethernet.py", "interfaces-tunnel.py", "interfaces-vxlan.py", "interfaces-wireguard.py", "interfaces-wireless.py", "interfaces-wwan.py", "lldp.py", "nat.py", "nat66.py", "ntp.py", "pki.py", "policy.py", "policy-local-route.py", "protocols_bfd.py", "protocols_bgp.py", "protocols_igmp.py", "protocols_isis.py", "protocols_mpls.py", "protocols_nhrp.py", "protocols_ospf.py", "protocols_ospfv3.py", "protocols_pim.py", "protocols_rip.py", "protocols_ripng.py", "protocols_static.py", "protocols_static_multicast.py", "salt-minion.py", "service_console-server.py", "service_ids_fastnetmon.py", "service_ipoe-server.py", "service_mdns-repeater.py", "service_pppoe-server.py", "service_router-advert.py", "ssh.py", "system-ip.py", "system-ipv6.py", "system-login-banner.py", "system-option.py", "system-syslog.py", "system-timezone.py", "system_console.py", "system_lcd.py", "task_scheduler.py", "tftp_server.py", "vpn_l2tp.py", "vpn_pptp.py", "vpn_sstp.py", "vrf.py", "vrf_vni.py", "vrrp.py" ] diff --git a/data/templates/netflow/uacctd.conf.tmpl b/data/templates/netflow/uacctd.conf.tmpl index 11fc76769..b6d31746f 100644 --- a/data/templates/netflow/uacctd.conf.tmpl +++ b/data/templates/netflow/uacctd.conf.tmpl @@ -1,75 +1,72 @@ # Genereated from VyOS configuration daemonize: true promisc: false pidfile: /var/run/uacctd.pid uacctd_group: 2 uacctd_nl_size: 2097152 -snaplen: {{ snaplen }} -{% if templatecfg['enable-egress'] != none %} -aggregate: in_iface,out_iface,src_mac,dst_mac,vlan,src_host,dst_host,src_port,dst_port,proto,tos,flows -{% else %} -aggregate: in_iface,src_mac,dst_mac,vlan,src_host,dst_host,src_port,dst_port,proto,tos,flows +snaplen: {{ packet_length }} +aggregate: in_iface{{ ',out_iface' if enable_egress is defined }},src_mac,dst_mac,vlan,src_host,dst_host,src_port,dst_port,proto,tos,flows +{% set pipe_size = buffer_size | int *1024 *1024 %} +plugin_pipe_size: {{ pipe_size }} +{# We need an integer division (//) without any remainder or fraction #} +plugin_buffer_size: {{ pipe_size // 1000 }} +{% if syslog_facility is defined and syslog_facility is not none %} +syslog: {{ syslog_facility }} {% endif %} -plugin_pipe_size: {{ templatecfg['plugin_pipe_size'] }} -plugin_buffer_size: {{ templatecfg['plugin_buffer_size'] }} -{% if templatecfg['syslog-facility'] != none %} -syslog: {{ templatecfg['syslog-facility'] }} -{% endif %} -{% if templatecfg['disable-imt'] == none %} +{% if disable_imt is not defined %} imt_path: /tmp/uacctd.pipe imt_mem_pools_number: 169 {% endif %} -plugins: {% if templatecfg['netflow']['servers'] != none %} -{% for server in templatecfg['netflow']['servers'] %} -{% if loop.last %}nfprobe[nf_{{ server['address'] }}]{% else %}nfprobe[nf_{{ server['address'] }}],{% endif %} -{% endfor %} -{% set plugins_presented = true %} -{% endif %} -{% if templatecfg['sflow']['servers'] != none %} -{% if plugins_presented %} -{% for server in templatecfg['sflow']['servers'] %},sfprobe[sf_{{ server['address'] }}]{% endfor %} -{% else %} -{% for server in templatecfg['sflow']['servers'] %} -{% if loop.last %}sfprobe[sf_{{ server['address'] }}]{% else %}sfprobe[sf_{{ server['address'] }}],{% endif %} -{% endfor %} -{% endif %} -{% set plugins_presented = true %} -{% endif %} -{% if templatecfg['disable-imt'] == none %} -{% if plugins_presented %},memory{% else %}memory{% endif %} -{% endif %} -{% if templatecfg['netflow']['servers'] != none %} -{% for server in templatecfg['netflow']['servers'] %} -nfprobe_receiver[nf_{{ server['address'] }}]: {{ server['address'] }}:{{ server['port'] }} -nfprobe_version[nf_{{ server['address'] }}]: {{ templatecfg['netflow']['version'] }} -{% if templatecfg['netflow']['engine-id'] != none %} -nfprobe_engine[nf_{{ server['address'] }}]: {{ templatecfg['netflow']['engine-id'] }} -{% endif %} -{% if templatecfg['netflow']['max-flows'] != none %} -nfprobe_maxflows[nf_{{ server['address'] }}]: {{ templatecfg['netflow']['max-flows'] }} -{% endif %} -{% if templatecfg['netflow']['sampling-rate'] != none %} -sampling_rate[nf_{{ server['address'] }}]: {{ templatecfg['netflow']['sampling-rate'] }} +{% set plugin = [] %} +{% if disable_imt is not defined %} +{% set plugin = ['memory'] %} {% endif %} -{% if templatecfg['netflow']['source-ip'] != none %} -nfprobe_source_ip[nf_{{ server['address'] }}]: {{ templatecfg['netflow']['source-ip'] }} -{% endif %} -{% if templatecfg['netflow']['timeout_string'] != '' %} -nfprobe_timeouts[nf_{{ server['address'] }}]: {{ templatecfg['netflow']['timeout_string'] }} +{% if netflow is defined and netflow.server is defined and netflow.server is not none %} +{% for server in netflow.server %} +{% set plugin = plugin.append('nfprobe[nf_' ~ server ~ ']') %} +{% endfor %} {% endif %} -{% endfor %} +{% if sflow is defined and sflow.server is defined and sflow.server is not none %} +{% for server in sflow.server %} +{% set plugin = plugin.append('sfprobe[sf_' ~ server ~ ']') %} +{% endfor %} {% endif %} +plugins: {{ plugin | join(',') }} -{% if templatecfg['sflow']['servers'] != none %} -{% for server in templatecfg['sflow']['servers'] %} -sfprobe_receiver[sf_{{ server['address'] }}]: {{ server['address'] }}:{{ server['port'] }} -sfprobe_agentip[sf_{{ server['address'] }}]: {{ templatecfg['sflow']['agent-address'] }} -{% if templatecfg['sflow']['sampling-rate'] != none %} -sampling_rate[sf_{{ server['address'] }}]: {{ templatecfg['sflow']['sampling-rate'] }} -{% endif %} -{% if templatecfg['sflow']['source-address'] != none %} -sfprobe_source_ip[sf_{{ server['address'] }}]: {{ templatecfg['sflow']['source-address'] }} +{% if netflow is defined and netflow.server is defined and netflow.server is not none %} +# NetFlow servers +{% for server, server_config in netflow.server.items() %} +nfprobe_receiver[nf_{{ server }}]: {{ server }}:{{ server_config.port }} +nfprobe_version[nf_{{ server }}]: {{ netflow.version }} +{% if netflow.engine_id is defined and netflow.engine_id is not none %} +nfprobe_engine[nf_{{ server }}]: {{ netflow.engine_id }} +{% endif %} +{% if netflow.max_flows is defined and netflow.max_flows is not none %} +nfprobe_maxflows[nf_{{ server }}]: {{ netflow.max_flows }} +{% endif %} +{% if netflow.sampling_rate is defined and netflow.sampling_rate is not none %} +sampling_rate[nf_{{ server }}]: {{ netflow.sampling_rate }} +{% endif %} +{% if netflow.source_address is defined and netflow.source_address is not none %} +nfprobe_source_ip[nf_{{ server }}]: {{ netflow.source_address }} +{% endif %} +{% if netflow.timeout is defined and netflow.timeout is not none %} +nfprobe_timeouts[nf_{{ server }}]: expint={{ netflow.timeout.expiry_interval }}:general={{ netflow.timeout.flow_generic }}:icmp={{ netflow.timeout.icmp }}:maxlife={{ netflow.timeout.max_active_life }}:tcp.fin={{ netflow.timeout.tcp_fin }}:tcp={{ netflow.timeout.tcp_generic }}:tcp.rst={{ netflow.timeout.tcp_rst }}:udp={{ netflow.timeout.udp }} +{% endif %} +{% endfor %} {% endif %} -{% endfor %} + +{% if sflow is defined and sflow.server is defined and sflow.server is not none %} +# sFlow servers +{% for server, server_config in sflow.server.items() %} +sfprobe_receiver[sf_{{ server }}]: {{ server }}:{{ server_config.port }} +sfprobe_agentip[sf_{{ server }}]: {{ sflow.agent_address }} +{% if sflow.sampling_rate is defined and sflow.sampling_rate is not none %} +sampling_rate[sf_{{ server }}]: {{ sflow.sampling_rate }} +{% endif %} +{% if sflow.source_address is defined and sflow.source_address is not none %} +sfprobe_source_ip[sf_{{ server }}]: {{ sflow.source_address }} +{% endif %} +{% endfor %} {% endif %} diff --git a/interface-definitions/flow-accounting-conf.xml.in b/interface-definitions/flow-accounting-conf.xml.in index 9f13c295b..1b57d706c 100644 --- a/interface-definitions/flow-accounting-conf.xml.in +++ b/interface-definitions/flow-accounting-conf.xml.in @@ -1,434 +1,438 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- flow-accounting configuration --> <interfaceDefinition> <node name="system"> <children> <node name="flow-accounting" owner="${vyos_conf_scripts_dir}/flow_accounting_conf.py"> <properties> <help>Flow accounting settings</help> <priority>990</priority> </properties> <children> <leafNode name="buffer-size"> <properties> <help>Buffer size</help> <valueHelp> <format>u32</format> - <description>Buffer size in MiB</description> + <description>Buffer size in MiB (default: 10)</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-4294967295"/> </constraint> </properties> + <defaultValue>10</defaultValue> + </leafNode> + <leafNode name="packet-length"> + <properties> + <help>Specifies the maximum number of bytes to capture for each packet</help> + <valueHelp> + <format>u32:128-750</format> + <description>Packet length in bytes (default: 128)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 128-750"/> + </constraint> + </properties> + <defaultValue>128</defaultValue> </leafNode> <leafNode name="enable-egress"> <properties> <help>Enable egress flow accounting</help> <valueless/> </properties> </leafNode> <leafNode name="disable-imt"> <properties> <help>Disable in memory table plugin</help> <valueless/> </properties> </leafNode> <leafNode name="syslog-facility"> <properties> <help>Syslog facility for flow-accounting</help> <completionHelp> <list>auth authpriv cron daemon kern lpr mail mark news protocols security syslog user uucp local0 local1 local2 local3 local4 local5 local6 local7 all</list> </completionHelp> <valueHelp> <format>auth</format> <description>Authentication and authorization</description> </valueHelp> <valueHelp> <format>authpriv</format> <description>Non-system authorization</description> </valueHelp> <valueHelp> <format>cron</format> <description>Cron daemon</description> </valueHelp> <valueHelp> <format>daemon</format> <description>System daemons</description> </valueHelp> <valueHelp> <format>kern</format> <description>Kernel</description> </valueHelp> <valueHelp> <format>lpr</format> <description>Line printer spooler</description> </valueHelp> <valueHelp> <format>mail</format> <description>Mail subsystem</description> </valueHelp> <valueHelp> <format>mark</format> <description>Timestamp</description> </valueHelp> <valueHelp> <format>news</format> <description>USENET subsystem</description> </valueHelp> <valueHelp> <format>protocols</format> <description>Routing protocols (local7)</description> </valueHelp> <valueHelp> <format>security</format> <description>Authentication and authorization</description> </valueHelp> <valueHelp> <format>syslog</format> <description>Authentication and authorization</description> </valueHelp> <valueHelp> <format>user</format> <description>Application processes</description> </valueHelp> <valueHelp> <format>uucp</format> <description>UUCP subsystem</description> </valueHelp> <valueHelp> <format>local0</format> <description>Local facility 0</description> </valueHelp> <valueHelp> <format>local1</format> <description>Local facility 1</description> </valueHelp> <valueHelp> <format>local2</format> <description>Local facility 2</description> </valueHelp> <valueHelp> <format>local3</format> <description>Local facility 3</description> </valueHelp> <valueHelp> <format>local4</format> <description>Local facility 4</description> </valueHelp> <valueHelp> <format>local5</format> <description>Local facility 5</description> </valueHelp> <valueHelp> <format>local6</format> <description>Local facility 6</description> </valueHelp> <valueHelp> <format>local7</format> <description>Local facility 7</description> </valueHelp> <valueHelp> <format>all</format> <description>Authentication and authorization</description> </valueHelp> <constraint> <regex>^(auth|authpriv|cron|daemon|kern|lpr|mail|mark|news|protocols|security|syslog|user|uucp|local0|local1|local2|local3|local4|local5|local6|local7|all)$</regex> </constraint> </properties> </leafNode> #include <include/generic-interface-multi.xml.i> <node name="netflow"> <properties> <help>NetFlow settings</help> </properties> <children> <leafNode name="engine-id"> <properties> <help>NetFlow engine-id</help> <valueHelp> <format>0-255 or 0-255:0-255</format> <description>NetFlow engine-id for v5</description> </valueHelp> <valueHelp> <format>u32</format> <description>NetFlow engine-id for v9 / IPFIX</description> </valueHelp> <constraint> <regex>(\d|[1-9]\d{1,8}|[1-3]\d{9}|4[01]\d{8}|42[0-8]\d{7}|429[0-3]\d{6}|4294[0-8]\d{5}|42949[0-5]\d{4}|429496[0-6]\d{3}|4294967[01]\d{2}|42949672[0-8]\d|429496729[0-5])$|^(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]):(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$</regex> </constraint> </properties> </leafNode> <leafNode name="max-flows"> <properties> <help>NetFlow maximum flows</help> <valueHelp> <format>u32</format> <description>NetFlow maximum flows</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-4294967295"/> </constraint> </properties> </leafNode> <leafNode name="sampling-rate"> <properties> <help>NetFlow sampling-rate</help> <valueHelp> <format>u32</format> <description>Sampling rate (1 in N packets)</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-4294967295"/> </constraint> </properties> </leafNode> - <leafNode name="source-ip"> - <properties> - <help>IPv4 or IPv6 source address of NetFlow packets</help> - <valueHelp> - <format>ipv4</format> - <description>IPv4 source address of NetFlow packets</description> - </valueHelp> - <valueHelp> - <format>ipv6</format> - <description>IPv6 source address of NetFlow packets</description> - </valueHelp> - <constraint> - <validator name="ipv4-address"/> - <validator name="ipv6-address"/> - </constraint> - </properties> - </leafNode> + #include <include/source-address-ipv4-ipv6.xml.i> <leafNode name="version"> <properties> <help>NetFlow version to export</help> <completionHelp> <list>5 9 10</list> </completionHelp> <valueHelp> <format>5</format> <description>NetFlow version 5</description> </valueHelp> <valueHelp> <format>9</format> <description>NetFlow version 9 (default)</description> </valueHelp> <valueHelp> <format>10</format> <description>Internet Protocol Flow Information Export (IPFIX)</description> </valueHelp> </properties> + <defaultValue>9</defaultValue> </leafNode> <tagNode name="server"> <properties> <help>Server to export NetFlow [REQUIRED]</help> <valueHelp> <format>ipv4</format> <description>IPv4 server to export NetFlow</description> </valueHelp> <valueHelp> <format>ipv6</format> <description>IPv6 server to export NetFlow</description> </valueHelp> <constraint> <validator name="ipv4-address"/> <validator name="ipv6-address"/> </constraint> </properties> <children> <leafNode name="port"> <properties> <help>NetFlow port number</help> <valueHelp> <format>u32:1025-65535</format> <description>NetFlow port number (default: 2055)</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1025-65535"/> </constraint> </properties> + <defaultValue>2055</defaultValue> </leafNode> </children> </tagNode> <node name="timeout"> <properties> <help>NetFlow timeout values</help> </properties> <children> <leafNode name="expiry-interval"> <properties> <help>Expiry scan interval</help> <valueHelp> <format>u32:0-2147483647</format> <description>Expiry scan interval (default: 60)</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-2147483647"/> </constraint> </properties> + <defaultValue>60</defaultValue> </leafNode> <leafNode name="flow-generic"> <properties> <help>Generic flow timeout value</help> <valueHelp> <format>u32:0-2147483647</format> <description>Generic flow timeout in seconds (default: 3600)</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-2147483647"/> </constraint> </properties> + <defaultValue>3600</defaultValue> </leafNode> <leafNode name="icmp"> <properties> <help>ICMP timeout value</help> <valueHelp> <format>u32:0-2147483647</format> <description>ICMP timeout in seconds (default: 300)</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-2147483647"/> </constraint> </properties> + <defaultValue>300</defaultValue> </leafNode> <leafNode name="max-active-life"> <properties> <help>Max active timeout value</help> <valueHelp> <format>u32:0-2147483647</format> <description>Max active timeout in seconds (default: 604800)</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-2147483647"/> </constraint> </properties> + <defaultValue>604800</defaultValue> </leafNode> <leafNode name="tcp-fin"> <properties> <help>TCP finish timeout value</help> <valueHelp> <format>u32:0-2147483647</format> <description>TCP FIN timeout in seconds (default: 300)</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-2147483647"/> </constraint> </properties> + <defaultValue>300</defaultValue> </leafNode> <leafNode name="tcp-generic"> <properties> <help>TCP generic timeout value</help> <valueHelp> <format>u32:0-2147483647</format> <description>TCP generic timeout in seconds (default: 3600)</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-2147483647"/> </constraint> </properties> + <defaultValue>3600</defaultValue> </leafNode> <leafNode name="tcp-rst"> <properties> <help>TCP reset timeout value</help> <valueHelp> <format>u32:0-2147483647</format> <description>TCP RST timeout in seconds (default: 120)</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-2147483647"/> </constraint> </properties> + <defaultValue>120</defaultValue> </leafNode> <leafNode name="udp"> <properties> <help>UDP timeout value</help> <valueHelp> <format>u32:0-2147483647</format> <description>UDP timeout in seconds (default: 300)</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-2147483647"/> </constraint> </properties> + <defaultValue>300</defaultValue> </leafNode> </children> </node> </children> </node> <node name="sflow"> <properties> <help>sFlow settings</help> </properties> <children> <leafNode name="agent-address"> <properties> <help>sFlow agent IPv4 address</help> <completionHelp> <list>auto</list> <script>${vyos_completion_dir}/list_local_ips.sh --ipv4</script> </completionHelp> - <valueHelp> - <format>auto</format> - <description>auto select sFlow agent-address (default)</description> - </valueHelp> <valueHelp> <format>ipv4</format> <description>sFlow IPv4 agent address</description> </valueHelp> <constraint> <validator name="ipv4-address"/> - <regex>^auto$</regex> </constraint> </properties> </leafNode> <leafNode name="sampling-rate"> <properties> <help>sFlow sampling-rate</help> <valueHelp> <format>u32</format> <description>Sampling rate (1 in N packets)</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-4294967295"/> </constraint> </properties> </leafNode> <tagNode name="server"> <properties> <help>Server to export sFlow [REQUIRED]</help> <valueHelp> <format>ipv4</format> <description>IPv4 server to export sFlow</description> </valueHelp> <valueHelp> <format>ipv6</format> <description>IPv6 server to export sFlow</description> </valueHelp> <constraint> <validator name="ipv4-address"/> <validator name="ipv6-address"/> </constraint> </properties> <children> <leafNode name="port"> <properties> <help>sFlow port number</help> <valueHelp> <format>u32:1025-65535</format> <description>sFlow port number (default: 6343)</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1025-65535"/> </constraint> </properties> + <defaultValue>6343</defaultValue> </leafNode> </children> </tagNode> #include <include/source-address-ipv4-ipv6.xml.i> </children> </node> </children> </node> </children> </node> </interfaceDefinition> diff --git a/smoketest/configs/bgp-big-as-cloud b/smoketest/configs/bgp-big-as-cloud index 694243d1e..10660ec87 100644 --- a/smoketest/configs/bgp-big-as-cloud +++ b/smoketest/configs/bgp-big-as-cloud @@ -1,1956 +1,1962 @@ firewall { all-ping enable broadcast-ping disable config-trap disable group { address-group bgp-peers-4 { address 192.0.68.3 address 192.0.68.2 address 192.0.176.193 address 192.0.52.0-192.0.52.255 address 192.0.53.0-192.0.53.255 address 192.0.16.209 address 192.0.192.0-192.0.192.255 address 192.0.193.0-192.0.193.255 address 192.0.194.0-192.0.194.255 address 192.0.195.0-192.0.195.255 address 192.0.196.0-192.0.196.255 address 192.0.197.0-192.0.197.255 address 192.0.198.0-192.0.198.255 address 192.0.199.0-192.0.199.255 } address-group vrrp-peers-4 { address 192.0.68.3 address 192.0.160.3 address 192.0.98.3 address 192.0.71.131 address 192.0.84.67 address 192.0.71.195 address 192.0.71.115 address 192.0.70.195 address 192.0.70.179 address 192.0.70.163 address 192.0.70.147 address 192.0.70.131 address 192.0.70.19 address 192.0.70.3 address 192.0.71.99 address 192.0.68.67 address 192.0.71.67 address 192.0.71.3 address 192.0.68.35 address 192.0.68.131 address 192.0.69.2 address 192.0.70.35 address 192.0.70.67 } ipv6-address-group bgp-peers-6 { address 2001:db8:c::3 address 2001:db8:1000::2e9 address 2001:db8:24::fb address 2001:db8:24::fc address 2001:db8:24::fd address 2001:db8:24::2e address 2001:db8:24::3d address 2001:db8:24::4a address 2001:db8:24::5e address 2001:db8:24::7 address 2001:db8:24::11 address 2001:db8:24::18 address 2001:db8:24::20 address 2001:db8:24::22 address 2001:db8:24::31 address 2001:db8:24::58 address 2001:db8:24::64 address 2001:db8:24::a5 address 2001:db8:24::aa address 2001:db8:24::ab address 2001:db8:24::b0 address 2001:db8:24::b3 address 2001:db8:24::bd address 2001:db8:24::c address 2001:db8:24::d2 address 2001:db8:24::d3 address 2001:db8:838::1 address 2001:db8::1a27:5051:c09d address 2001:db8::1a27:5051:c19d address 2001:db8::20ad:0:1 address 2001:db8::2306:0:1 address 2001:db8::2ca:0:1 address 2001:db8::2ca:0:2 address 2001:db8::2ca:0:3 address 2001:db8::2ca:0:4 } ipv6-address-group vrrp-peers-6 { address fe80::fe89:15cf } ipv6-network-group AS64512-6 { network 2001::/29 } network-group AS64512-4 { network 192.0.68.0/22 network 192.0.98.0/24 network 192.0.160.0/24 network 192.0.84.0/22 } } ipv6-name management-to-local-6 { default-action reject enable-default-log } ipv6-name management-to-peers-6 { default-action reject enable-default-log } ipv6-name management-to-servers-6 { default-action reject enable-default-log } ipv6-name peers-to-local-6 { default-action reject enable-default-log rule 500 { action accept protocol icmpv6 } rule 501 { action accept protocol vrrp source { group { address-group vrrp-peers-6 } } } rule 502 { action accept destination { port bgp } protocol tcp source { group { address-group bgp-peers-6 } } } rule 503 { action accept protocol tcp source { group { address-group bgp-peers-6 } port bgp } } } ipv6-name peers-to-management-6 { default-action reject enable-default-log } ipv6-name peers-to-servers-6 { default-action reject enable-default-log rule 9990 { action reject source { group { network-group AS64512-6 } } } rule 9999 { action accept destination { group { network-group AS64512-6 } } } } ipv6-name servers-to-local-6 { default-action reject enable-default-log rule 500 { action accept protocol icmpv6 } rule 501 { action accept protocol vrrp source { group { address-group vrrp-peers-6 } } } rule 511 { action accept protocol tcp_udp source { port 53 } } } ipv6-name servers-to-management-6 { default-action reject enable-default-log } ipv6-name servers-to-peers-6 { default-action reject enable-default-log rule 51 { action accept source { group { network-group AS64512-6 } } } } ipv6-receive-redirects disable ipv6-src-route disable ip-src-route disable log-martians enable name management-to-local-4 { default-action reject enable-default-log rule 500 { action accept protocol icmp } rule 501 { action accept destination { port 22 } protocol tcp } rule 502 { action accept destination { port snmp } protocol udp } } name management-to-peers-4 { default-action reject enable-default-log } name management-to-servers-4 { default-action reject enable-default-log } name peers-to-local-4 { default-action reject enable-default-log rule 500 { action accept protocol icmp } rule 501 { action accept protocol vrrp source { group { address-group vrrp-peers-4 } } } rule 502 { action accept destination { port bgp } protocol tcp source { group { address-group bgp-peers-4 } } } rule 503 { action accept protocol tcp source { group { address-group bgp-peers-4 } port bgp } } } name peers-to-management-4 { default-action reject enable-default-log } name peers-to-servers-4 { default-action reject enable-default-log rule 9990 { action reject source { group { network-group AS64512-4 } } } rule 9999 { action accept destination { group { network-group AS64512-4 } } } } name servers-to-local-4 { default-action reject enable-default-log rule 500 { action accept protocol icmp } rule 501 { action accept protocol vrrp source { group { address-group vrrp-peers-4 } } } rule 511 { action accept protocol tcp_udp source { port 53 } } } name servers-to-management-4 { default-action reject enable-default-log } name servers-to-peers-4 { default-action reject enable-default-log rule 51 { action accept source { group { network-group AS64512-4 } } } } receive-redirects disable send-redirects enable source-validation disable syn-cookies enable twa-hazards-protection disable } high-availability { vrrp { group 11-4 { interface eth0.11 priority 200 virtual-address 192.0.68.1/27 vrid 4 } group 11-6 { interface eth0.11 priority 200 virtual-address 2001:db8:c::1/64 vrid 6 } group 102-4 { interface eth0.102 priority 200 virtual-address 192.0.98.1/24 vrid 4 } group 102-6 { interface eth0.102 priority 200 virtual-address 2001:db8:0:102::1/64 vrid 6 } group 105-4 { interface eth0.105 priority 200 virtual-address 192.0.160.1/24 vrid 4 } group 105-6 { interface eth0.105 priority 200 virtual-address 2001:db8:0:105::1/64 vrid 6 } group 1001-4 { interface eth0.1001 priority 200 virtual-address 192.0.68.33/27 vrid 4 } group 1001-6 { interface eth0.1001 priority 200 virtual-address 2001:db8:0:1001::1/64 vrid 6 } group 1002-4 { interface eth0.1002 priority 200 virtual-address 192.0.68.65/26 vrid 4 } group 1002-6 { interface eth0.1002 priority 200 virtual-address 2001:db8:0:1002::1/64 vrid 6 } group 1003-4 { interface eth0.1003 priority 200 virtual-address 192.0.68.129/25 vrid 4 } group 1003-6 { interface eth0.1003 priority 200 virtual-address 2001:db8:0:1003::1/64 vrid 6 } group 1004-4 { interface eth0.1004 priority 200 virtual-address 192.0.69.1/24 vrid 4 } group 1004-6 { interface eth0.1004 priority 200 virtual-address 2001:db8:0:1004::1/64 vrid 6 } group 1005-4 { interface eth0.1005 priority 200 virtual-address 192.0.70.1/28 vrid 4 } group 1005-6 { interface eth0.1005 priority 200 virtual-address 2001:db8:0:1005::1/64 vrid 6 } group 1006-4 { interface eth0.1006 priority 200 virtual-address 192.0.70.17/28 vrid 4 } group 1006-6 { interface eth0.1006 priority 200 virtual-address 2001:db8:0:1006::1/64 vrid 6 } group 1007-4 { interface eth0.1007 priority 200 virtual-address 192.0.70.33/27 vrid 4 } group 1007-6 { interface eth0.1007 priority 200 virtual-address 2001:db8:0:1007::1/64 vrid 6 } group 1008-4 { interface eth0.1008 priority 200 virtual-address 192.0.70.65/26 vrid 4 } group 1008-6 { interface eth0.1008 priority 200 virtual-address 2001:db8:0:1008::1/64 vrid 6 } group 1009-4 { interface eth0.1009 priority 200 virtual-address 192.0.70.129/28 vrid 4 } group 1009-6 { interface eth0.1009 priority 200 virtual-address 2001:db8:0:1009::1/64 vrid 6 } group 1010-4 { interface eth0.1010 priority 200 virtual-address 192.0.70.145/28 vrid 4 } group 1010-6 { interface eth0.1010 priority 200 virtual-address 2001:db8:0:1010::1/64 vrid 6 } group 1011-4 { interface eth0.1011 priority 200 virtual-address 192.0.70.161/28 vrid 4 } group 1011-6 { interface eth0.1011 priority 200 virtual-address 2001:db8:0:1011::1/64 vrid 6 } group 1012-4 { interface eth0.1012 priority 200 virtual-address 192.0.70.177/28 vrid 4 } group 1012-6 { interface eth0.1012 priority 200 virtual-address 2001:db8:0:1012::1/64 vrid 6 } group 1013-4 { interface eth0.1013 priority 200 virtual-address 192.0.70.193/27 vrid 4 } group 1013-6 { interface eth0.1013 priority 200 virtual-address 2001:db8:0:1013::1/64 vrid 6 } group 1014-4 { interface eth0.1014 priority 200 virtual-address 192.0.84.65/26 vrid 4 } group 1014-6 { interface eth0.1014 priority 200 virtual-address 2001:db8:0:1014::1/64 vrid 6 } group 1015-4 { interface eth0.1015 priority 200 virtual-address 192.0.71.1/26 vrid 4 } group 1015-6 { interface eth0.1015 priority 200 virtual-address 2001:db8:0:1015::1/64 vrid 6 } group 1016-4 { interface eth0.1016 priority 200 virtual-address 192.0.71.65/27 vrid 4 } group 1016-6 { interface eth0.1016 priority 200 virtual-address 2001:db8:0:1016::1/64 vrid 6 } group 1017-4 { interface eth0.1017 priority 200 virtual-address 192.0.71.97/28 vrid 4 } group 1017-6 { interface eth0.1017 priority 200 virtual-address 2001:db8:0:1017::1/64 vrid 6 } group 1018-4 { interface eth0.1018 priority 200 virtual-address 192.0.71.113/28 vrid 4 } group 1018-6 { interface eth0.1018 priority 200 virtual-address 2001:db8:0:1018::1/64 vrid 6 } group 1019-4 { interface eth0.1019 priority 200 virtual-address 192.0.71.129/26 vrid 4 } group 1019-6 { interface eth0.1019 priority 200 virtual-address 2001:db8:0:1019::1/64 vrid 6 } group 1020-4 { interface eth0.1020 priority 200 virtual-address 192.0.71.193/26 vrid 4 } group 1020-6 { interface eth0.1020 priority 200 virtual-address 2001:db8:0:1020::1/64 vrid 6 } } } interfaces { ethernet eth0 { address 192.0.0.11/16 duplex auto smp-affinity auto speed auto vif 11 { address 192.0.68.2/27 address 2001:db8:c::2/64 } vif 102 { address 192.0.98.2/24 address 2001:db8:0:102::2/64 } vif 105 { address 192.0.160.2/24 address 2001:db8:0:105::2/64 } vif 838 { address 192.0.16.210/30 address 2001:db8:838::2/64 } vif 886 { address 192.0.193.224/21 address 2001:db8::3:669:0:1/64 } vif 1001 { address 192.0.68.34/27 address 2001:db8:0:1001::2/64 } vif 1002 { address 192.0.68.66/26 address 2001:db8:0:1002::2/64 } vif 1003 { address 192.0.68.130/25 address 2001:db8:0:1003::2/64 } vif 1004 { address 192.0.69.2/24 address 2001:db8:0:1004::2/64 } vif 1005 { address 192.0.70.2/28 address 2001:db8:0:1005::2/64 } vif 1006 { address 192.0.70.18/28 address 2001:db8:0:1006::2/64 } vif 1007 { address 192.0.70.34/27 address 2001:db8:0:1007::2/64 } vif 1008 { address 192.0.70.66/26 address 2001:db8:0:1008::2/64 } vif 1009 { address 192.0.70.130/28 address 2001:db8:0:1009::2/64 } vif 1010 { address 192.0.70.146/28 address 2001:db8:0:1010::2/64 } vif 1011 { address 192.0.70.162/28 address 2001:db8:0:1011::2/64 } vif 1012 { address 192.0.70.178/28 address 2001:db8:0:1012::2/64 } vif 1013 { address 192.0.70.194/27 address 2001:db8:0:1013::3/64 } vif 1014 { address 192.0.84.66/26 address 2001:db8:0:1014::2/64 } vif 1015 { address 192.0.71.2/26 address 2001:db8:0:1015::2/64 } vif 1016 { address 192.0.71.66/27 address 2001:db8:0:1016::2/64 } vif 1017 { address 192.0.71.98/28 address 2001:db8:0:1017::2/64 } vif 1018 { address 192.0.71.114/28 address 2001:db8:0:1018::2/64 } vif 1019 { address 192.0.71.130/26 address 2001:db8:0:1019::2/64 } vif 1020 { address 192.0.71.194/26 address 2001:db8:0:1020::2/64 } vif 4088 { address 2001:db8:24::c7/64 address 192.0.52.199/23 } vif 4089 { address 192.0.176.194/30 address 2001:db8:1000::2ea/126 } } loopback lo { } } policy { as-path-list AS64513-AS64514 { rule 10 { action permit regex "^64513 64514$" } } as-path-list AS64512 { rule 10 { action permit regex ^$ } } prefix-list defaultV4 { rule 10 { action permit prefix 0.0.0.0/0 } } prefix-list hostrouteV4 { rule 10 { action permit ge 32 prefix 192.0.160.0/24 } rule 20 { action permit ge 32 prefix 192.0.98.0/24 } rule 30 { action permit ge 32 prefix 192.0.68.0/22 } rule 40 { action permit ge 32 prefix 192.0.84.0/22 } } prefix-list vyosV4 { rule 10 { action permit prefix 192.0.160.0/24 } rule 20 { action permit prefix 192.0.98.0/24 } rule 30 { action permit prefix 192.0.68.0/22 } rule 40 { action permit prefix 192.0.84.0/22 } } prefix-list privateV4 { rule 10 { action permit le 32 prefix 192.0.0.0/8 } rule 20 { action permit le 32 prefix 192.0.0.0/12 } rule 30 { action permit le 32 prefix 192.0.0.0/16 } } prefix-list6 all6 { rule 10 { action permit ge 4 prefix 2000::/3 } } prefix-list6 hostrouteV6 { rule 20 { action permit ge 128 prefix 2001:db8::/29 } } prefix-list6 vyosV6 { rule 20 { action permit prefix 2001:db8::/29 } } prefix-list6 privateV6 { rule 10 { action permit prefix fc00::/7 } } route-map ExportRouteMap { rule 5 { action permit match { as-path AS64512 ip { address { prefix-list hostrouteV4 } } } set { community 65000:666 } } rule 10 { action permit match { as-path AS64512 ip { address { prefix-list vyosV4 } } } } rule 15 { action permit match { as-path AS64512 ipv6 { address { prefix-list hostrouteV6 } } } set { community 65000:666 } } rule 20 { action permit match { as-path AS64512 ipv6 { address { prefix-list vyosV6 } } } } rule 100 { action deny } } route-map ExportRouteMapAS64515 { rule 10 { action permit match { ipv6 { address { prefix-list all6 } } } } rule 20 { action deny match { ip { address { prefix-list defaultV4 } } } } rule 100 { action deny } } route-map ExportRouteMapAS64516 { rule 5 { action permit match { as-path AS64512 ip { address { prefix-list hostrouteV4 } } } set { community 65000:666 } } rule 10 { action permit match { as-path AS64512 ip { address { prefix-list vyosV4 } } } } rule 15 { action permit match { as-path AS64512 ipv6 { address { prefix-list hostrouteV6 } } } set { community 65000:666 } } rule 20 { action permit match { as-path AS64512 ipv6 { address { prefix-list vyosV6 } } } } rule 100 { action deny } } route-map ExportRouteMapAS64517 { rule 5 { action permit match { as-path AS64512 ip { address { prefix-list hostrouteV4 } } } set { community 64517:666 } } rule 10 { action permit match { as-path AS64512 ip { address { prefix-list vyosV4 } } } } rule 15 { action permit match { as-path AS64512 ipv6 { address { prefix-list hostrouteV6 } } } set { community 64517:666 } } rule 20 { action permit match { as-path AS64512 ipv6 { address { prefix-list vyosV6 } } } } rule 100 { action deny } } route-map ExportRouteMapAS64513 { rule 5 { action permit match { as-path AS64512 ip { address { prefix-list hostrouteV4 } } } set { community 64513:666 } } rule 10 { action permit match { as-path AS64512 ip { address { prefix-list vyosV4 } } } } rule 15 { action permit match { as-path AS64512 ipv6 { address { prefix-list hostrouteV6 } } } set { community 64513:666 } } rule 20 { action permit match { as-path AS64512 ipv6 { address { prefix-list vyosV6 } } } } rule 100 { action deny } } route-map ImportRouteMap { rule 10 { action deny match { ip { address { prefix-list privateV4 } } } } rule 15 { action deny match { ipv6 { address { prefix-list privateV6 } } } } rule 20 { action deny match { ip { address { prefix-list vyosV4 } } } } rule 30 { action deny match { ipv6 { address { prefix-list vyosV6 } } } } rule 40 { action deny match { as-path AS64512 } } rule 50 { action permit match { as-path AS64513-AS64514 } set { weight 10001 } } rule 65535 { action permit } } } protocols { bgp 64500 { address-family { ipv4-unicast { network 192.0.98.0/24 { } network 192.0.160.0/24 { } network 192.0.68.0/22 { } network 192.0.84.0/22 { } redistribute { static { route-map ExportRouteMap } } } ipv6-unicast { network 2001:db8::/29 { } redistribute { static { route-map ExportRouteMap } } } } maximum-paths { ebgp 8 ibgp 16 } neighbor 192.0.16.209 { address-family { ipv4-unicast { route-map { export ExportRouteMapAS64516 import ImportRouteMap } } } remote-as 64501 } neighbor 192.0.192.6 { address-family { ipv4-unicast { maximum-prefix 100 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64502 } neighbor 192.0.192.157 { address-family { ipv4-unicast { maximum-prefix 350000 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64503 } neighbor 192.0.192.228 { address-family { ipv4-unicast { maximum-prefix 10000 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64504 } neighbor 192.0.193.157 { address-family { ipv4-unicast { maximum-prefix 350000 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64505 } neighbor 192.0.193.202 { address-family { ipv4-unicast { maximum-prefix 10000 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64506 } neighbor 192.0.193.223 { address-family { ipv4-unicast { maximum-prefix 10000 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64507 } neighbor 192.0.194.161 { address-family { ipv4-unicast { maximum-prefix 10000 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64508 } neighbor 192.0.194.171 { address-family { ipv4-unicast { maximum-prefix 10000 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64509 } neighbor 192.0.176.193 { address-family { ipv4-unicast { route-map { export ExportRouteMapAS64516 import ImportRouteMap } } } remote-as 64510 } neighbor 192.0.52.12 { address-family { ipv4-unicast { maximum-prefix 300 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64511 } neighbor 192.0.52.17 { address-family { ipv4-unicast { maximum-prefix 75 route-map { export ExportRouteMap import ImportRouteMap } } } password vyosvyos remote-as 64512 } neighbor 192.0.52.24 { address-family { ipv4-unicast { maximum-prefix 300 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64513 } neighbor 192.0.52.32 { address-family { ipv4-unicast { maximum-prefix 50 route-map { export ExportRouteMap import ImportRouteMap } } } password vyosfoooo remote-as 64514 } neighbor 192.0.52.34 { address-family { ipv4-unicast { maximum-prefix 10 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64515 } neighbor 192.0.52.46 { address-family { ipv4-unicast { maximum-prefix 10 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64516 } neighbor 192.0.52.49 { address-family { ipv4-unicast { maximum-prefix 75 route-map { export ExportRouteMap import ImportRouteMap } } } password secret remote-as 64517 } neighbor 192.0.52.74 { address-family { ipv4-unicast { maximum-prefix 15000 route-map { export ExportRouteMap import ImportRouteMap } } } password secretvyos remote-as 64518 } neighbor 192.0.52.94 { address-family { ipv4-unicast { maximum-prefix 250 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64519 } neighbor 192.0.52.100 { address-family { ipv4-unicast { maximum-prefix 50 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64520 } neighbor 192.0.52.119 { address-family { ipv4-unicast { maximum-prefix 30 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64521 } neighbor 192.0.52.165 { address-family { ipv4-unicast { maximum-prefix 50 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64522 } neighbor 192.0.52.170 { address-family { ipv4-unicast { maximum-prefix 150000 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64523 } neighbor 192.0.52.171 { address-family { ipv4-unicast { maximum-prefix 10000 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64524 } neighbor 192.0.52.179 { address-family { ipv4-unicast { maximum-prefix 20 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64525 } neighbor 192.0.52.189 { address-family { ipv4-unicast { maximum-prefix 1000 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64526 } neighbor 192.0.52.210 { address-family { ipv4-unicast { maximum-prefix 15 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64527 } neighbor 192.0.52.211 { address-family { ipv4-unicast { maximum-prefix 15 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64528 } neighbor 192.0.52.251 { address-family { ipv4-unicast { route-map { export ExportRouteMap import ImportRouteMap } weight 1010 } } remote-as 64529 } neighbor 192.0.52.252 { address-family { ipv4-unicast { route-map { export ExportRouteMap } weight 1010 } } remote-as 64530 } neighbor 192.0.52.253 { address-family { ipv4-unicast { route-map { export ExportRouteMapAS64515 import ImportRouteMap } } } passive remote-as 64531 } neighbor 192.0.68.3 { address-family { ipv4-unicast { nexthop-self soft-reconfiguration { inbound } } } remote-as 64532 update-source 192.0.68.2 } neighbor 2001:db8:838::1 { address-family { ipv6-unicast { route-map { export ExportRouteMapAS64516 import ImportRouteMap } } } remote-as 64533 } neighbor 2001:db8:c::3 { address-family { ipv6-unicast { nexthop-self soft-reconfiguration { inbound } } } remote-as 64534 update-source 2001:db8:c::2 } neighbor 2001:db8:24::2e { address-family { ipv6-unicast { maximum-prefix 5 route-map { export ExportRouteMap import ImportRouteMap } } } password vyossecret remote-as 64535 } neighbor 2001:db8:24::4a { address-family { ipv6-unicast { maximum-prefix 1000 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64536 } neighbor 2001:db8:24::5e { address-family { ipv6-unicast { maximum-prefix 200 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64537 } neighbor 2001:db8:24::11 { address-family { ipv6-unicast { maximum-prefix 20 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64538 } neighbor 2001:db8:24::18 { address-family { ipv6-unicast { maximum-prefix 300 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64539 } neighbor 2001:db8:24::20 { address-family { ipv6-unicast { maximum-prefix 10 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64540 } neighbor 2001:db8:24::22 { address-family { ipv6-unicast { maximum-prefix 5 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64541 } neighbor 2001:db8:24::31 { address-family { ipv6-unicast { maximum-prefix 20 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64542 } neighbor 2001:db8:24::58 { address-family { ipv6-unicast { maximum-prefix 15 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64543 } neighbor 2001:db8:24::64 { address-family { ipv6-unicast { maximum-prefix 10 route-map { export ExportRouteMap import ImportRouteMap } } } password geheim remote-as 64544 } neighbor 2001:db8:24::a5 { address-family { ipv6-unicast { maximum-prefix 10 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64545 } neighbor 2001:db8:24::aa { address-family { ipv6-unicast { route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64546 } neighbor 2001:db8:24::ab { address-family { ipv6-unicast { maximum-prefix 1800 route-map { export ExportRouteMap import ImportRouteMap } } } remote-as 64547 } neighbor 2001:db8:24::b0 { address-family { ipv6-unicast { maximum-prefix 5 route-map { export ExportRouteMap import ImportRouteMap } } } password secret123 remote-as 64548 } parameters { default { no-ipv4-unicast } log-neighbor-changes router-id 192.0.68.2 } } static { route 192.0.98.0/24 { blackhole { } } route 192.0.160.0/24 { blackhole { } } route 192.0.68.0/22 { blackhole { } } route 192.0.84.0/22 { blackhole { } } route6 2001:db8::/29 { blackhole { } } } } system { config-management { commit-revisions 100 } console { device ttyS0 { speed 115200 } } flow-accounting { disable-imt interface eth0.4088 interface eth0.4089 netflow { engine-id 1 server 192.0.2.55 { port 2055 } version 9 } + sflow { + agent-address auto + server 1.2.3.4 { + port 1234 + } + } syslog-facility daemon } host-name vyos login { user vyos { authentication { encrypted-password $6$2Ta6TWHd/U$NmrX0x9kexCimeOcYK1MfhMpITF9ELxHcaBU/znBq.X2ukQOj61fVI2UYP/xBzP4QtiTcdkgs7WOQMHWsRymO/ plaintext-password "" } } } name-server 2001:db8::1 name-server 2001:db8::2 name-server 192.0.2.1 name-server 192.0.2.2 ntp { server 0.pool.ntp.org { } server 1.pool.ntp.org { } server 2.pool.ntp.org { } } syslog { global { facility all { level all } preserve-fqdn } } time-zone Europe/Zurich } zone-policy { zone local { default-action drop from management { firewall { ipv6-name management-to-local-6 name management-to-local-4 } } from peers { firewall { ipv6-name peers-to-local-6 name peers-to-local-4 } } from servers { firewall { ipv6-name servers-to-local-6 name servers-to-local-4 } } local-zone } zone management { default-action reject from peers { firewall { ipv6-name peers-to-management-6 name peers-to-management-4 } } from servers { firewall { ipv6-name servers-to-management-6 name servers-to-management-4 } } interface eth0 } zone peers { default-action reject from management { firewall { ipv6-name management-to-peers-6 name management-to-peers-4 } } from servers { firewall { ipv6-name servers-to-peers-6 name servers-to-peers-4 } } interface eth0.4088 interface eth0.4089 interface eth0.11 interface eth0.838 interface eth0.886 } zone servers { default-action reject from management { firewall { ipv6-name management-to-servers-6 name management-to-servers-4 } } from peers { firewall { ipv6-name peers-to-servers-6 name peers-to-servers-4 } } interface eth0.1001 interface eth0.105 interface eth0.102 interface eth0.1019 interface eth0.1014 interface eth0.1020 interface eth0.1018 interface eth0.1013 interface eth0.1012 interface eth0.1011 interface eth0.1010 interface eth0.1009 interface eth0.1006 interface eth0.1005 interface eth0.1017 interface eth0.1016 interface eth0.1002 interface eth0.1015 interface eth0.1003 interface eth0.1004 interface eth0.1007 interface eth0.1008 } } /* Warning: Do not remove the following line. */ /* === vyatta-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack-sync@1:conntrack@1:dhcp-relay@2:dhcp-server@5:dns-forwarding@1:firewall@5:ipsec@5:l2tp@1:mdns@1:nat@4:ntp@1:pptp@1:qos@1:quagga@6:snmp@1:ssh@1:system@9:vrrp@2:wanloadbalance@3:webgui@1:webproxy@1:webproxy@2:zone-policy@1" === */ /* Release version: 1.2.5 */ diff --git a/smoketest/scripts/cli/test_system_flow-accounting.py b/smoketest/scripts/cli/test_system_flow-accounting.py index 57866a198..f3bed635c 100755 --- a/smoketest/scripts/cli/test_system_flow-accounting.py +++ b/smoketest/scripts/cli/test_system_flow-accounting.py @@ -1,228 +1,228 @@ #!/usr/bin/env python3 # # Copyright (C) 2021 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import unittest from base_vyostest_shim import VyOSUnitTestSHIM from vyos.configsession import ConfigSessionError from vyos.ifconfig import Section from vyos.util import cmd from vyos.util import process_named_running from vyos.util import read_file PROCESS_NAME = 'uacctd' base_path = ['system', 'flow-accounting'] uacctd_conf = '/etc/pmacct/uacctd.conf' class TestSystemFlowAccounting(VyOSUnitTestSHIM.TestCase): @classmethod def setUpClass(cls): super(cls, cls).setUpClass() # ensure we can also run this test on a live system - so lets clean # out the current configuration :) cls.cli_delete(cls, base_path) def tearDown(self): self.cli_delete(base_path) self.cli_commit() # after service removal process must no longer run self.assertFalse(process_named_running(PROCESS_NAME)) def test_basic(self): buffer_size = '5' # MiB syslog = 'all' self.cli_set(base_path + ['buffer-size', buffer_size]) self.cli_set(base_path + ['syslog-facility', syslog]) # You need to configure at least one interface for flow-accounting with self.assertRaises(ConfigSessionError): self.cli_commit() for interface in Section.interfaces('ethernet'): self.cli_set(base_path + ['interface', interface]) # commit changes self.cli_commit() # verify configuration tmp = cmd('sudo iptables-save -t raw') for interface in Section.interfaces('ethernet'): self.assertIn(f'-A VYATTA_CT_PREROUTING_HOOK -i {interface} -m comment --comment FLOW_ACCOUNTING_RULE -j NFLOG --nflog-group 2 --nflog-size 128 --nflog-threshold 100', tmp) uacctd = read_file(uacctd_conf) # circular queue size - buffer_size tmp = int(buffer_size) *1024 *1024 self.assertIn(f'plugin_pipe_size: {tmp}', uacctd) # transfer buffer size - recommended value from pmacct developers 1/1000 of pipe size tmp = int(buffer_size) *1024 *1024 # do an integer division tmp //= 1000 self.assertIn(f'plugin_buffer_size: {tmp}', uacctd) # when 'disable-imt' is not configured on the CLI it must be present self.assertIn(f'imt_path: /tmp/uacctd.pipe', uacctd) self.assertIn(f'imt_mem_pools_number: 169', uacctd) self.assertIn(f'syslog: {syslog}', uacctd) self.assertIn(f'plugins: memory', uacctd) def test_sflow(self): sampling_rate = '4000' source_address = '192.0.2.1' dummy_if = 'dum3841' agent_address = '192.0.2.2' sflow_server = { '1.2.3.4' : { }, '5.6.7.8' : { 'port' : '6000' } } self.cli_set(['interfaces', 'dummy', dummy_if, 'address', agent_address + '/32']) self.cli_set(base_path + ['disable-imt']) # You need to configure at least one interface for flow-accounting with self.assertRaises(ConfigSessionError): self.cli_commit() for interface in Section.interfaces('ethernet'): self.cli_set(base_path + ['interface', interface]) # You need to configure at least one sFlow or NetFlow protocol, or not # set "disable-imt" for flow-accounting with self.assertRaises(ConfigSessionError): self.cli_commit() self.cli_set(base_path + ['sflow', 'agent-address', agent_address]) self.cli_set(base_path + ['sflow', 'sampling-rate', sampling_rate]) self.cli_set(base_path + ['sflow', 'source-address', source_address]) for server, server_config in sflow_server.items(): self.cli_set(base_path + ['sflow', 'server', server]) if 'port' in server_config: self.cli_set(base_path + ['sflow', 'server', server, 'port', server_config['port']]) # commit changes self.cli_commit() uacctd = read_file(uacctd_conf) # when 'disable-imt' is not configured on the CLI it must be present self.assertNotIn(f'imt_path: /tmp/uacctd.pipe', uacctd) self.assertNotIn(f'imt_mem_pools_number: 169', uacctd) self.assertNotIn(f'plugins: memory', uacctd) for server, server_config in sflow_server.items(): if 'port' in server_config: self.assertIn(f'sfprobe_receiver[sf_{server}]: {server}', uacctd) else: self.assertIn(f'sfprobe_receiver[sf_{server}]: {server}:6343', uacctd) self.assertIn(f'sfprobe_agentip[sf_{server}]: {agent_address}', uacctd) self.assertIn(f'sampling_rate[sf_{server}]: {sampling_rate}', uacctd) self.assertIn(f'sfprobe_source_ip[sf_{server}]: {source_address}', uacctd) self.cli_delete(['interfaces', 'dummy', dummy_if]) def test_netflow(self): engine_id = '33' max_flows = '667' sampling_rate = '100' source_address = '192.0.2.1' dummy_if = 'dum3842' agent_address = '192.0.2.10' version = '10' tmo_expiry = '120' tmo_flow = '1200' tmo_icmp = '60' tmo_max = '50000' tmo_tcp_fin = '100' tmo_tcp_generic = '120' tmo_tcp_rst = '99' tmo_udp = '10' netflow_server = { '11.22.33.44' : { }, '55.66.77.88' : { 'port' : '6000' } } self.cli_set(['interfaces', 'dummy', dummy_if, 'address', agent_address + '/32']) for interface in Section.interfaces('ethernet'): self.cli_set(base_path + ['interface', interface]) self.cli_set(base_path + ['netflow', 'engine-id', engine_id]) self.cli_set(base_path + ['netflow', 'max-flows', max_flows]) self.cli_set(base_path + ['netflow', 'sampling-rate', sampling_rate]) self.cli_set(base_path + ['netflow', 'source-ip', source_address]) self.cli_set(base_path + ['netflow', 'version', version]) # timeouts self.cli_set(base_path + ['netflow', 'timeout', 'expiry-interval', tmo_expiry]) self.cli_set(base_path + ['netflow', 'timeout', 'flow-generic', tmo_flow]) self.cli_set(base_path + ['netflow', 'timeout', 'icmp', tmo_icmp]) self.cli_set(base_path + ['netflow', 'timeout', 'max-active-life', tmo_max]) self.cli_set(base_path + ['netflow', 'timeout', 'tcp-fin', tmo_tcp_fin]) self.cli_set(base_path + ['netflow', 'timeout', 'tcp-generic', tmo_tcp_generic]) self.cli_set(base_path + ['netflow', 'timeout', 'tcp-rst', tmo_tcp_rst]) self.cli_set(base_path + ['netflow', 'timeout', 'udp', tmo_udp]) # You need to configure at least one netflow server with self.assertRaises(ConfigSessionError): self.cli_commit() for server, server_config in netflow_server.items(): self.cli_set(base_path + ['netflow', 'server', server]) if 'port' in server_config: self.cli_set(base_path + ['netflow', 'server', server, 'port', server_config['port']]) # commit changes self.cli_commit() uacctd = read_file(uacctd_conf) - tmp = 'plugins: ' + tmp = [] + tmp.append('memory') for server, server_config in netflow_server.items(): - tmp += f'nfprobe[nf_{server}],' - tmp += 'memory' - self.assertIn(f'{tmp}', uacctd) + tmp.append(f'nfprobe[nf_{server}]') + self.assertIn('plugins: ' + ','.join(tmp), uacctd) for server, server_config in netflow_server.items(): self.assertIn(f'nfprobe_engine[nf_{server}]: {engine_id}', uacctd) self.assertIn(f'nfprobe_maxflows[nf_{server}]: {max_flows}', uacctd) self.assertIn(f'sampling_rate[nf_{server}]: {sampling_rate}', uacctd) self.assertIn(f'nfprobe_source_ip[nf_{server}]: {source_address}', uacctd) self.assertIn(f'nfprobe_version[nf_{server}]: {version}', uacctd) if 'port' in server_config: self.assertIn(f'nfprobe_receiver[nf_{server}]: {server}', uacctd) else: self.assertIn(f'nfprobe_receiver[nf_{server}]: {server}:2055', uacctd) self.assertIn(f'nfprobe_timeouts[nf_{server}]: expint={tmo_expiry}:general={tmo_flow}:icmp={tmo_icmp}:maxlife={tmo_max}:tcp.fin={tmo_tcp_fin}:tcp={tmo_tcp_generic}:tcp.rst={tmo_tcp_rst}:udp={tmo_udp}', uacctd) self.cli_delete(['interfaces', 'dummy', dummy_if]) if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/src/conf_mode/flow_accounting_conf.py b/src/conf_mode/flow_accounting_conf.py index daad00067..3d3b03e10 100755 --- a/src/conf_mode/flow_accounting_conf.py +++ b/src/conf_mode/flow_accounting_conf.py @@ -1,392 +1,279 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2020 VyOS maintainers and contributors +# Copyright (C) 2018-2021 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import os import re + from sys import exit import ipaddress from ipaddress import ip_address -from jinja2 import FileSystemLoader, Environment +from vyos.config import Config +from vyos.configdict import dict_merge from vyos.ifconfig import Section from vyos.ifconfig import Interface -from vyos.config import Config -from vyos import ConfigError -from vyos.util import cmd from vyos.template import render - +from vyos.util import cmd +from vyos.validate import is_addr_assigned +from vyos.xml import defaults +from vyos import ConfigError from vyos import airbag airbag.enable() -# default values -default_sflow_server_port = 6343 -default_netflow_server_port = 2055 -default_plugin_pipe_size = 10 -default_captured_packet_size = 128 -default_netflow_version = '9' -default_sflow_agentip = 'auto' uacctd_conf_path = '/etc/pmacct/uacctd.conf' iptables_nflog_table = 'raw' iptables_nflog_chain = 'VYATTA_CT_PREROUTING_HOOK' egress_iptables_nflog_table = 'mangle' egress_iptables_nflog_chain = 'FORWARD' -# helper functions -# check if node exists and return True if this is true -def _node_exists(path): - vyos_config = Config() - if vyos_config.exists(path): - return True - -# get sFlow agent-ip if agent-address is "auto" (default behaviour) -def _sflow_default_agentip(config): - # check if any of BGP, OSPF, OSPFv3 protocols are configured and use router-id from there - if config.exists('protocols bgp'): - bgp_router_id = config.return_value("protocols bgp {} parameters router-id".format(config.list_nodes('protocols bgp')[0])) - if bgp_router_id: - return bgp_router_id - if config.return_value('protocols ospf parameters router-id'): - return config.return_value('protocols ospf parameters router-id') - if config.return_value('protocols ospfv3 parameters router-id'): - return config.return_value('protocols ospfv3 parameters router-id') - - # if router-id was not found, use first available ip of any interface - for iface in Section.interfaces(): - for address in Interface(iface).get_addr(): - # return an IP, if this is not loopback - regex_filter = re.compile('^(?!(127)|(::1)|(fe80))(?P<ipaddr>[a-f\d\.:]+)/\d+$') - if regex_filter.search(address): - return regex_filter.search(address).group('ipaddr') - - # return nothing by default - return None - # get iptables rule dict for chain in table def _iptables_get_nflog(chain, table): # define list with rules rules = [] # prepare regex for parsing rules rule_pattern = "^-A (?P<rule_definition>{0} (\-i|\-o) (?P<interface>[\w\.\*\-]+).*--comment FLOW_ACCOUNTING_RULE.* -j NFLOG.*$)".format(chain) rule_re = re.compile(rule_pattern) for iptables_variant in ['iptables', 'ip6tables']: # run iptables, save output and split it by lines iptables_command = f'{iptables_variant} -t {table} -S {chain}' tmp = cmd(iptables_command, message='Failed to get flows list') # parse each line and add information to list for current_rule in tmp.splitlines(): current_rule_parsed = rule_re.search(current_rule) if current_rule_parsed: rules.append({ 'interface': current_rule_parsed.groupdict()["interface"], 'iptables_variant': iptables_variant, 'table': table, 'rule_definition': current_rule_parsed.groupdict()["rule_definition"] }) # return list with rules return rules # modify iptables rules -def _iptables_config(configured_ifaces, direction): +def _iptables_config(configured_ifaces, direction, length): # define list of iptables commands to modify settings iptable_commands = [] iptables_chain = iptables_nflog_chain iptables_table = iptables_nflog_table if direction == "egress": iptables_chain = egress_iptables_nflog_chain iptables_table = egress_iptables_nflog_table # prepare extended list with configured interfaces configured_ifaces_extended = [] for iface in configured_ifaces: configured_ifaces_extended.append({ 'iface': iface, 'iptables_variant': 'iptables' }) configured_ifaces_extended.append({ 'iface': iface, 'iptables_variant': 'ip6tables' }) # get currently configured interfaces with iptables rules active_nflog_rules = _iptables_get_nflog(iptables_chain, iptables_table) # compare current active list with configured one and delete excessive interfaces, add missed active_nflog_ifaces = [] for rule in active_nflog_rules: iptables = rule['iptables_variant'] interface = rule['interface'] if interface not in configured_ifaces: table = rule['table'] rule = rule['rule_definition'] iptable_commands.append(f'{iptables} -t {table} -D {rule}') else: active_nflog_ifaces.append({ 'iface': interface, 'iptables_variant': iptables, }) # do not create new rules for already configured interfaces for iface in active_nflog_ifaces: if iface in active_nflog_ifaces and iface in configured_ifaces_extended: configured_ifaces_extended.remove(iface) # create missed rules for iface_extended in configured_ifaces_extended: iface = iface_extended['iface'] iptables = iface_extended['iptables_variant'] iptables_op = "-i" if direction == "egress": iptables_op = "-o" - rule_definition = f'{iptables_chain} {iptables_op} {iface} -m comment --comment FLOW_ACCOUNTING_RULE -j NFLOG --nflog-group 2 --nflog-size {default_captured_packet_size} --nflog-threshold 100' + rule_definition = f'{iptables_chain} {iptables_op} {iface} -m comment --comment FLOW_ACCOUNTING_RULE -j NFLOG --nflog-group 2 --nflog-size {length} --nflog-threshold 100' iptable_commands.append(f'{iptables} -t {iptables_table} -I {rule_definition}') # change iptables for command in iptable_commands: cmd(command, raising=ConfigError) -def get_config(): - vc = Config() - vc.set_level('') - # Convert the VyOS config to an abstract internal representation - flow_config = { - 'flow-accounting-configured': vc.exists('system flow-accounting'), - 'buffer-size': vc.return_value('system flow-accounting buffer-size'), - 'enable-egress': _node_exists('system flow-accounting enable-egress'), - 'disable-imt': _node_exists('system flow-accounting disable-imt'), - 'syslog-facility': vc.return_value('system flow-accounting syslog-facility'), - 'interfaces': None, - 'sflow': { - 'configured': vc.exists('system flow-accounting sflow'), - 'agent-address': vc.return_value('system flow-accounting sflow agent-address'), - 'sampling-rate': vc.return_value('system flow-accounting sflow sampling-rate'), - 'servers': None, - 'source-address': vc.return_value('system flow-accounting sflow source-address') - }, - 'netflow': { - 'configured': vc.exists('system flow-accounting netflow'), - 'engine-id': vc.return_value('system flow-accounting netflow engine-id'), - 'max-flows': vc.return_value('system flow-accounting netflow max-flows'), - 'sampling-rate': vc.return_value('system flow-accounting netflow sampling-rate'), - 'source-ip': vc.return_value('system flow-accounting netflow source-ip'), - 'version': vc.return_value('system flow-accounting netflow version'), - 'timeout': { - 'expint': vc.return_value('system flow-accounting netflow timeout expiry-interval'), - 'general': vc.return_value('system flow-accounting netflow timeout flow-generic'), - 'icmp': vc.return_value('system flow-accounting netflow timeout icmp'), - 'maxlife': vc.return_value('system flow-accounting netflow timeout max-active-life'), - 'tcp.fin': vc.return_value('system flow-accounting netflow timeout tcp-fin'), - 'tcp': vc.return_value('system flow-accounting netflow timeout tcp-generic'), - 'tcp.rst': vc.return_value('system flow-accounting netflow timeout tcp-rst'), - 'udp': vc.return_value('system flow-accounting netflow timeout udp') - }, - 'servers': None - } - } - - # get interfaces list - if vc.exists('system flow-accounting interface'): - flow_config['interfaces'] = vc.return_values('system flow-accounting interface') - - # get sFlow collectors list - if vc.exists('system flow-accounting sflow server'): - flow_config['sflow']['servers'] = [] - sflow_collectors = vc.list_nodes('system flow-accounting sflow server') - for collector in sflow_collectors: - port = default_sflow_server_port - if vc.return_value("system flow-accounting sflow server {} port".format(collector)): - port = vc.return_value("system flow-accounting sflow server {} port".format(collector)) - flow_config['sflow']['servers'].append({ 'address': collector, 'port': port }) - - # get NetFlow collectors list - if vc.exists('system flow-accounting netflow server'): - flow_config['netflow']['servers'] = [] - netflow_collectors = vc.list_nodes('system flow-accounting netflow server') - for collector in netflow_collectors: - port = default_netflow_server_port - if vc.return_value("system flow-accounting netflow server {} port".format(collector)): - port = vc.return_value("system flow-accounting netflow server {} port".format(collector)) - flow_config['netflow']['servers'].append({ 'address': collector, 'port': port }) - - # get sflow agent-id - if flow_config['sflow']['agent-address'] == None or flow_config['sflow']['agent-address'] == 'auto': - flow_config['sflow']['agent-address'] = _sflow_default_agentip(vc) - - # get NetFlow version - if not flow_config['netflow']['version']: - flow_config['netflow']['version'] = default_netflow_version - - # convert NetFlow engine-id format, if this is necessary - if flow_config['netflow']['engine-id'] and flow_config['netflow']['version'] == '5': - regex_filter = re.compile('^\d+$') - if regex_filter.search(flow_config['netflow']['engine-id']): - flow_config['netflow']['engine-id'] = "{}:0".format(flow_config['netflow']['engine-id']) - - # return dict with flow-accounting configuration - return flow_config - -def verify(config): - # Verify that configuration is valid - # skip all checks if flow-accounting was removed - if not config['flow-accounting-configured']: - return True +def get_config(config=None): + if config: + conf = config + else: + conf = Config() + base = ['system', 'flow-accounting'] + if not conf.exists(base): + return None + + flow_accounting = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) + + # We have gathered the dict representation of the CLI, but there are default + # options which we need to update into the dictionary retrived. + default_values = defaults(base) + + # delete individual flow type default - should only be added if user uses + # this feature + for flow_type in ['sflow', 'netflow']: + if flow_type in default_values: + del default_values[flow_type] + flow_accounting = dict_merge(default_values, flow_accounting) + + for flow_type in ['sflow', 'netflow']: + if flow_type in flow_accounting: + default_values = defaults(base + [flow_type]) + # we need to merge individual server configurations + if 'server' in default_values: + del default_values['server'] + flow_accounting[flow_type] = dict_merge(default_values, flow_accounting[flow_type]) + + if 'server' in flow_accounting[flow_type]: + default_values = defaults(base + [flow_type, 'server']) + for server in flow_accounting[flow_type]['server']: + flow_accounting[flow_type]['server'][server] = dict_merge( + default_values,flow_accounting[flow_type]['server'][server]) + + return flow_accounting + +def verify(flow_config): + if not flow_config: + return None # check if at least one collector is enabled - if not (config['sflow']['configured'] or config['netflow']['configured'] or not config['disable-imt']): - raise ConfigError("You need to configure at least one sFlow or NetFlow protocol, or not set \"disable-imt\" for flow-accounting") + if 'sflow' not in flow_config and 'netflow' not in flow_config and 'disable_imt' in flow_config: + raise ConfigError('You need to configure at least sFlow or NetFlow, ' \ + 'or not set "disable-imt" for flow-accounting!') # Check if at least one interface is configured - if not config['interfaces']: - raise ConfigError("You need to configure at least one interface for flow-accounting") + if 'interface' not in flow_config: + raise ConfigError('Flow accounting requires at least one interface to ' \ + 'be configured!') # check that all configured interfaces exists in the system - for iface in config['interfaces']: - if not iface in Section.interfaces(): - # chnged from error to warning to allow adding dynamic interfaces and interface templates - # raise ConfigError("The {} interface is not presented in the system".format(iface)) - print("Warning: the {} interface is not presented in the system".format(iface)) + for interface in flow_config['interface']: + if interface not in Section.interfaces(): + # Changed from error to warning to allow adding dynamic interfaces + # and interface templates + print(f'Warning: Interface "{interface}" is not presented in the system') # check sFlow configuration - if config['sflow']['configured']: - # check if at least one sFlow collector is configured if sFlow configuration is presented - if not config['sflow']['servers']: - raise ConfigError("You need to configure at least one sFlow server") + if 'sflow' in flow_config: + # check if at least one sFlow collector is configured + if 'server' not in flow_config['sflow']: + raise ConfigError('You need to configure at least one sFlow server!') # check that all sFlow collectors use the same IP protocol version sflow_collector_ipver = None - for sflow_collector in config['sflow']['servers']: + for server in flow_config['sflow']['server']: if sflow_collector_ipver: - if sflow_collector_ipver != ip_address(sflow_collector['address']).version: + if sflow_collector_ipver != ip_address(server).version: raise ConfigError("All sFlow servers must use the same IP protocol") else: - sflow_collector_ipver = ip_address(sflow_collector['address']).version - + sflow_collector_ipver = ip_address(server).version # check agent-id for sFlow: we should avoid mixing IPv4 agent-id with IPv6 collectors and vice-versa - for sflow_collector in config['sflow']['servers']: - if ip_address(sflow_collector['address']).version != ip_address(config['sflow']['agent-address']).version: - raise ConfigError("Different IP address versions cannot be mixed in \"sflow agent-address\" and \"sflow server\". You need to set manually the same IP version for \"agent-address\" as for all sFlow servers") - - # check if configured sFlow agent-id exist in the system - agent_id_presented = None - for iface in Section.interfaces(): - for address in Interface(iface).get_addr(): - # check an IP, if this is not loopback - regex_filter = re.compile('^(?!(127)|(::1)|(fe80))(?P<ipaddr>[a-f\d\.:]+)/\d+$') - if regex_filter.search(address): - if regex_filter.search(address).group('ipaddr') == config['sflow']['agent-address']: - agent_id_presented = True - break - if not agent_id_presented: - raise ConfigError("Your \"sflow agent-address\" does not exist in the system") + for server in flow_config['sflow']['server']: + if 'agent_address' in flow_config['sflow']: + if ip_address(server).version != ip_address(flow_config['sflow']['agent_address']).version: + raise ConfigError('IPv4 and IPv6 addresses can not be mixed in "sflow agent-address" and "sflow '\ + 'server". You need to set the same IP version for both "agent-address" and '\ + 'all sFlow servers') + + if 'agent_address' in flow_config['sflow']: + if not is_addr_assigned(agent_address): + tmp = flow_config['sflow']['agent_address'] + print(f'Warning: Configured "sflow agent-address {tmp}" does not exist in the system!') # check NetFlow configuration - if config['netflow']['configured']: + if 'netflow' in flow_config: # check if at least one NetFlow collector is configured if NetFlow configuration is presented - if not config['netflow']['servers']: - raise ConfigError("You need to configure at least one NetFlow server") + if 'server' not in flow_config['netflow']: + raise ConfigError('You need to configure at least one NetFlow server!') # check if configured netflow source-ip exist in the system - if config['netflow']['source-ip']: - source_ip_presented = None - for iface in Section.interfaces(): - for address in Interface(iface).get_addr(): - # check an IP - regex_filter = re.compile('^(?!(127)|(::1)|(fe80))(?P<ipaddr>[a-f\d\.:]+)/\d+$') - if regex_filter.search(address): - if regex_filter.search(address).group('ipaddr') == config['netflow']['source-ip']: - source_ip_presented = True - break - if not source_ip_presented: - print("Warning: your \"netflow source-ip\" does not exist in the system") + if 'source_address' in flow_config['netflow']: + if not is_addr_assigned(flow_config['netflow']['source_address']): + tmp = flow_config['netflow']['source_address'] + print(f'Warning: Configured "netflow source-address {tmp}" does not exist on the system!') # check if engine-id compatible with selected protocol version - if config['netflow']['engine-id']: + if 'engine_id' in flow_config['netflow']: v5_filter = '^(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]):(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$' v9v10_filter = '^(\d|[1-9]\d{1,8}|[1-3]\d{9}|4[01]\d{8}|42[0-8]\d{7}|429[0-3]\d{6}|4294[0-8]\d{5}|42949[0-5]\d{4}|429496[0-6]\d{3}|4294967[01]\d{2}|42949672[0-8]\d|429496729[0-5])$' - if config['netflow']['version'] == '5': + engine_id = flow_config['netflow']['engine_id'] + version = flow_config['netflow']['version'] + + if flow_config['netflow']['version'] == '5': regex_filter = re.compile(v5_filter) - if not regex_filter.search(config['netflow']['engine-id']): - raise ConfigError("You cannot use NetFlow engine-id {} together with NetFlow protocol version {}".format(config['netflow']['engine-id'], config['netflow']['version'])) + if not regex_filter.search(engine_id): + raise ConfigError(f'You cannot use NetFlow engine-id "{engine_id}" '\ + f'together with NetFlow protocol version "{version}"!') else: regex_filter = re.compile(v9v10_filter) - if not regex_filter.search(config['netflow']['engine-id']): + if not regex_filter.search(flow_config['netflow']['engine_id']): raise ConfigError("You cannot use NetFlow engine-id {} together with NetFlow protocol version {}".format(config['netflow']['engine-id'], config['netflow']['version'])) # return True if all checks were passed return True -def generate(config): - # skip all checks if flow-accounting was removed - if not config['flow-accounting-configured']: - return True - - # Calculate all necessary values - if config['buffer-size']: - # circular queue size - config['plugin_pipe_size'] = int(config['buffer-size']) * 1024**2 - else: - config['plugin_pipe_size'] = default_plugin_pipe_size * 1024**2 - # transfer buffer size - # recommended value from pmacct developers 1/1000 of pipe size - config['plugin_buffer_size'] = int(config['plugin_pipe_size'] / 1000) - - # Prepare a timeouts string - timeout_string = '' - for timeout_type, timeout_value in config['netflow']['timeout'].items(): - if timeout_value: - if timeout_string == '': - timeout_string = "{}{}={}".format(timeout_string, timeout_type, timeout_value) - else: - timeout_string = "{}:{}={}".format(timeout_string, timeout_type, timeout_value) - config['netflow']['timeout_string'] = timeout_string - - render(uacctd_conf_path, 'netflow/uacctd.conf.tmpl', { - 'templatecfg': config, - 'snaplen': default_captured_packet_size, - }) +def generate(flow_config): + if not flow_config: + return None + render(uacctd_conf_path, 'netflow/uacctd.conf.tmpl', flow_config) -def apply(config): - # define variables - command = None +def apply(flow_config): + action = 'restart' # Check if flow-accounting was removed and define command - if not config['flow-accounting-configured']: - command = 'systemctl stop uacctd.service' - else: - command = 'systemctl restart uacctd.service' + if not flow_config: + _iptables_config([], 'ingress', flow_config['packet_length']) + _iptables_config([], 'egress', flow_config['packet_length']) - # run command to start or stop flow-accounting - cmd(command, raising=ConfigError, message='Failed to start/stop flow-accounting') + # Stop flow-accounting daemon + cmd('systemctl stop uacctd.service') + return + + # Start/reload flow-accounting daemon + cmd(f'systemctl restart uacctd.service') # configure iptables rules for defined interfaces - if config['interfaces']: - _iptables_config(config['interfaces'], 'ingress') + if 'interface' in flow_config: + _iptables_config(flow_config['interface'], 'ingress', flow_config['packet_length']) # configure egress the same way if configured otherwise remove it - if config['enable-egress']: - _iptables_config(config['interfaces'], 'egress') + if 'enable_egress' in flow_config: + _iptables_config(flow_config['interface'], 'egress', flow_config['packet_length']) else: - _iptables_config([], 'egress') - else: - _iptables_config([], 'ingress') - _iptables_config([], 'egress') + _iptables_config([], 'egress', flow_config['packet_length']) if __name__ == '__main__': try: config = get_config() verify(config) generate(config) apply(config) except ConfigError as e: print(e) exit(1) diff --git a/src/migration-scripts/flow-accounting/0-to-1 b/src/migration-scripts/flow-accounting/0-to-1 new file mode 100755 index 000000000..72cce77b0 --- /dev/null +++ b/src/migration-scripts/flow-accounting/0-to-1 @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# T4099: flow-accounting: sync "source-ip" and "source-address" between netflow +# and sflow ion CLI +# T4105: flow-accounting: drop "sflow agent-address auto" + +from sys import argv +from vyos.configtree import ConfigTree + +if (len(argv) < 1): + print("Must specify file name!") + exit(1) + +file_name = argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +base = ['system', 'flow-accounting'] +config = ConfigTree(config_file) + +if not config.exists(base): + # Nothing to do + exit(0) + +# T4099 +tmp = base + ['netflow', 'source-ip'] +if config.exists(tmp): + config.rename(tmp, 'source-address') + +# T4105 +tmp = base + ['sflow', 'agent-address'] +if config.exists(tmp): + value = config.return_value(tmp) + if value == 'auto': + # delete the "auto" + config.delete(tmp) + + # 1) check if BGP router-id is set + # 2) check if OSPF router-id is set + # 3) check if OSPFv3 router-id is set + router_id = None + for protocol in ['bgp', 'ospf', 'ospfv3']: + if config.exists(['protocols', protocol, 'parameters', 'router-id']): + router_id = config.return_value(['protocols', protocol, 'parameters', 'router-id']) + break + if router_id: + config.set(tmp, value=router_id) + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print("Failed to save the modified config: {}".format(e)) + exit(1)