diff options
author | Christian Poessinger <christian@poessinger.com> | 2021-05-11 19:15:51 +0200 |
---|---|---|
committer | Christian Poessinger <christian@poessinger.com> | 2021-05-14 21:39:46 +0200 |
commit | 4d11715bd936d5d111bb3cd6e289ef2b3c3c218a (patch) | |
tree | 1ab899b54aa57d2e12dc60c4f6b0ef67af3b0b30 | |
parent | 0ab290275fac027672eb9613500b8705ab64fe72 (diff) | |
download | vyos-1x-4d11715bd936d5d111bb3cd6e289ef2b3c3c218a.tar.gz vyos-1x-4d11715bd936d5d111bb3cd6e289ef2b3c3c218a.zip |
conntrack: T3535: migrate codebase from vyatta-conntrack-sync
-rw-r--r-- | data/templates/conntrackd/conntrackd.conf.tmpl | 107 | ||||
-rw-r--r-- | debian/control | 3 | ||||
-rw-r--r-- | interface-definitions/service_conntrack-sync.xml.in | 168 | ||||
-rwxr-xr-x | src/conf_mode/conntrack_sync.py | 106 | ||||
-rw-r--r-- | src/etc/systemd/system/conntrackd.service.d/override.conf | 8 | ||||
-rwxr-xr-x | src/migration-scripts/conntrack-sync/1-to-2 | 61 | ||||
-rwxr-xr-x | src/validators/ipv4 | 3 | ||||
-rwxr-xr-x | src/validators/ipv4-multicast | 3 | ||||
-rwxr-xr-x | src/validators/ipv6-multicast | 3 |
9 files changed, 462 insertions, 0 deletions
diff --git a/data/templates/conntrackd/conntrackd.conf.tmpl b/data/templates/conntrackd/conntrackd.conf.tmpl new file mode 100644 index 000000000..86501023f --- /dev/null +++ b/data/templates/conntrackd/conntrackd.conf.tmpl @@ -0,0 +1,107 @@ +# autogenerated by conntrack_sync.py + +# Synchronizer settings +Sync { + Mode FTFW { + DisableExternalCache {{ 'on' if disable_external_cache is defined else 'off' }} + } +{% for iface, iface_config in interface.items() %} +{% if loop.first %} +{% if iface_config.peer is defined and iface_config.peer is not none %} + UDP { +{% if listen_address is defined and listen_address is not none %} + IPv4_address {{ listen_address }} +{% endif %} + IPv4_Destination_Address {{ iface_config.peer }} + Port 3780 +{% else %} +{% set ip_address = iface | get_ipv4 %} + Multicast { + IPv4_address {{ mcast_group }} + Group 3780 + IPv4_interface {{ ip_address[0] | ip_from_cidr }} +{% endif %} + Interface {{ iface }} +{% endif %} +{% endfor %} + SndSocketBuffer {{ sync_queue_size | int *1024 *1024 }} + RcvSocketBuffer {{ sync_queue_size | int *1024 *1024 }} + Checksum on + } +{% if expect_sync is defined and expect_sync is not none %} + Options { +{% if 'all' in expect_sync %} + ExpectationSync on +{% else %} + ExpectationSync { +{% for protocol in expect_sync %} + {{ protocol }} +{% endfor %} +{% endif %} + } + } +{% endif %} +} +Helper { + Type rpc inet tcp { + QueueNum 3 + Policy rpc { + ExpectMax 1 + ExpectTimeout 300 + } + } + Type rpc inet udp { + QueueNum 4 + Policy rpc { + ExpectMax 1 + ExpectTimeout 300 + } + } + Type tns inet tcp { + QueueNum 5 + Policy tns { + ExpectMax 1 + ExpectTimeout 300 + } + } +} + +# General settings +General { + Nice -20 + HashSize {{ hash_size }} + HashLimit {{ table_size | int *2 }} + LogFile off + Syslog on + LockFile /var/lock/conntrack.lock + UNIX { + Path /run/conntrackd/conntrackd.ctl + Backlog 20 + } + NetlinkBufferSize {{ 2 *1024 *1024 }} + NetlinkBufferSizeMaxGrowth {{ event_listen_queue_size | int *1024 *1024 }} + NetlinkOverrunResync off + NetlinkEventsReliable on +{% if ignore_address is defined or accept_protocol is defined %} + Filter From Userspace { +{% if ignore_address is defined and ignore_address is not none %} + Address Ignore { +{% for address in ignore_address if address | is_ipv4 %} + IPv4_address {{ address }} +{% endfor %} +{% for address in ignore_address if address | is_ipv6 %} + IPv6_address {{ address }} +{% endfor %} + } +{% endif %} +{% if accept_protocol is defined and accept_protocol is not none %} + Protocol Accept { +{% for protocol in accept_protocol %} + {{ protocol | upper }} +{% endfor %} + } +{% endif %} + } +{% endif %} +} + diff --git a/debian/control b/debian/control index 851152d95..de030310e 100644 --- a/debian/control +++ b/debian/control @@ -35,6 +35,7 @@ Depends: bmon, bsdmainutils, conntrack, + conntrackd, conserver-client, conserver-server, console-data, @@ -67,6 +68,8 @@ Depends: lcdproc, libatomic1, libndp-tools, + libnetfilter-conntrack3, + libnfnetlink0, libpam-radius-auth (>= 1.5.0), libvyosconfig0, lldpd, diff --git a/interface-definitions/service_conntrack-sync.xml.in b/interface-definitions/service_conntrack-sync.xml.in new file mode 100644 index 000000000..45d211479 --- /dev/null +++ b/interface-definitions/service_conntrack-sync.xml.in @@ -0,0 +1,168 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="service"> + <children> + <node name="conntrack-sync" owner="${vyos_conf_scripts_dir}/conntrack_sync.py"> + <properties> + <help>Connection tracking synchronization</help> + <priority>995</priority> + </properties> + <children> + <leafNode name="accept-protocol"> + <properties> + <help>Protocols for which local conntrack entries will be synced</help> + <completionHelp> + <list>tcp udp icmp sctp</list> + </completionHelp> + <valueHelp> + <format>tcp</format> + <description>Sync Transmission Control Protocol conntrack entries</description> + </valueHelp> + <valueHelp> + <format>udp</format> + <description>Sync User Datagram Protocol conntrack entries</description> + </valueHelp> + <valueHelp> + <format>icmp</format> + <description>Sync Internet Control Message Protocol conntrack entries</description> + </valueHelp> + <valueHelp> + <format>sctp</format> + <description>Sync Stream Control Transmission Protocol conntrack entries</description> + </valueHelp> + <constraint> + <regex>^(tcp|udp|icmp|sctp)$</regex> + </constraint> + <constraintErrorMessage>Allowed protocols: tcp udp icmp or sctp</constraintErrorMessage> + <multi/> + </properties> + </leafNode> + <leafNode name="disable-external-cache"> + <properties> + <help>Directly injects the flow-states into the in-kernel Connection Tracking System of the backup firewall.</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="event-listen-queue-size"> + <properties> + <help>Queue size for local conntrack events</help> + <valueHelp> + <format>u32</format> + <description>Queue size in MB</description> + </valueHelp> + </properties> + <defaultValue>8</defaultValue> + </leafNode> + <leafNode name="expect-sync"> + <properties> + <help>Protocol for which expect entries need to be synchronized</help> + <completionHelp> + <list>all ftp sip h323 nfs sqlnet</list> + </completionHelp> + <constraint> + <regex>^(all|ftp|sip|h323|nfs|sqlnet)$</regex> + </constraint> + <constraintErrorMessage>Invalid protocol</constraintErrorMessage> + <multi/> + </properties> + </leafNode> + <node name="failover-mechanism"> + <properties> + <help>Failover mechanism to use for conntrack-sync</help> + </properties> + <children> + <node name="cluster"> + <properties> + <help>Cluster as failover-mechanism to use for conntrack-sync</help> + </properties> + <children> + <leafNode name="group"> + <properties> + <help>Cluster group [DEPRECATED]</help> + </properties> + </leafNode> + </children> + </node> + <node name="vrrp"> + <properties> + <help>VRRP as failover-mechanism to use for conntrack-sync</help> + </properties> + <children> + <leafNode name="sync-group"> + <properties> + <help>VRRP sync group [REQUIRED]</help> + <completionHelp> + <path>high-availability vrrp sync-group</path> + </completionHelp> + </properties> + </leafNode> + </children> + </node> + </children> + </node> + <leafNode name="ignore-address"> + <properties> + <help>IP addresses for which local conntrack entries will not be synced</help> + <valueHelp> + <format>ipv4</format> + <description>IPv4 address to ignore</description> + </valueHelp> + <valueHelp> + <format>ipv4net</format> + <description>IPv4 prefix to ignore</description> + </valueHelp> + <valueHelp> + <format>ipv6</format> + <description>IPv6 address to ignore</description> + </valueHelp> + <valueHelp> + <format>ipv6net</format> + <description>IPv6 prefix to ignore</description> + </valueHelp> + <constraint> + <validator name="ipv4"/> + <validator name="ipv6"/> + </constraint> + <multi/> + </properties> + </leafNode> + <tagNode name="interface"> + <properties> + <help>Interface to use for syncing conntrack entries</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py --bridgeable</script> + </completionHelp> + </properties> + <children> + <leafNode name="peer"> + <properties> + <help>IP address of the peer to send the UDP conntrack info too. This disable multicast.</help> + </properties> + </leafNode> + </children> + </tagNode> + #include <include/listen-address-ipv4.xml.i> + <leafNode name="mcast-group"> + <properties> + <help>Multicast group to use for syncing conntrack entries</help> + <constraint> + <validator name="ipv4-multicast"/> + </constraint> + </properties> + <defaultValue>225.0.0.50</defaultValue> + </leafNode> + <leafNode name="sync-queue-size"> + <properties> + <help>Queue size for syncing conntrack entries</help> + <valueHelp> + <format>u32</format> + <description>Queue size in MB</description> + </valueHelp> + </properties> + <defaultValue>1</defaultValue> + </leafNode> + </children> + </node> + </children> + </node> +</interfaceDefinition> diff --git a/src/conf_mode/conntrack_sync.py b/src/conf_mode/conntrack_sync.py new file mode 100755 index 000000000..c1c90d1fc --- /dev/null +++ b/src/conf_mode/conntrack_sync.py @@ -0,0 +1,106 @@ +#!/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 os + +from sys import exit +from vyos.config import Config +from vyos.configdict import dict_merge +from vyos.configverify import verify_interface_exists +from vyos.util import call +from vyos.util import read_file +from vyos.template import render +from vyos.template import get_ipv4 +from vyos.validate import is_addr_assigned +from vyos.xml import defaults +from vyos import ConfigError +from vyos import airbag +airbag.enable() + +config_file = '/run/conntrackd/conntrackd.conf' + +def get_config(config=None): + if config: + conf = config + else: + conf = Config() + base = ['service', 'conntrack-sync'] + if not conf.exists(base): + return None + + conntrack = 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) + conntrack = dict_merge(default_values, conntrack) + + conntrack['hash_size'] = read_file('/sys/module/nf_conntrack/parameters/hashsize') + conntrack['table_size'] = read_file('/proc/sys/net/netfilter/nf_conntrack_max') + + return conntrack + +def verify(conntrack): + if not conntrack: + return None + + if 'interface' not in conntrack: + raise ConfigError('Interface not defined!') + + for interface in conntrack['interface']: + verify_interface_exists(interface) + # Interface must not only exist, it must also carry an IP address + if len(get_ipv4(interface)) < 1: + raise ConfigError(f'Interface {interface} requires an IP address!') + + if 'expect_sync' in conntrack: + if len(conntrack['expect_sync']) > 1 and 'all' in conntrack['expect_sync']: + raise ConfigError('Cannot configure all with other protocol') + + if 'listen_address' in conntrack: + address = conntrack['listen_address'] + if not is_addr_assigned(address): + raise ConfigError(f'Specified listen-address {address} not assigned to any interface!') + + return None + +def generate(conntrack): + if not conntrack: + if os.path.isfile(config_file): + os.unlink(config_file) + return None + + render(config_file, 'conntrackd/conntrackd.conf.tmpl', conntrack) + + return None + +def apply(conntrack): + if not conntrack: + call('systemctl stop conntrackd.service') + return None + + call('systemctl restart conntrackd.service') + return None + +if __name__ == '__main__': + try: + c = get_config() + verify(c) + generate(c) + apply(c) + except ConfigError as e: + print(e) + exit(1) diff --git a/src/etc/systemd/system/conntrackd.service.d/override.conf b/src/etc/systemd/system/conntrackd.service.d/override.conf new file mode 100644 index 000000000..eb611e0d9 --- /dev/null +++ b/src/etc/systemd/system/conntrackd.service.d/override.conf @@ -0,0 +1,8 @@ +[Unit] +After= +After=vyos-router.service +ConditionPathExists=/run/conntrackd/conntrackd.conf + +[Service] +ExecStart= +ExecStart=/usr/sbin/conntrackd -C /run/conntrackd/conntrackd.conf diff --git a/src/migration-scripts/conntrack-sync/1-to-2 b/src/migration-scripts/conntrack-sync/1-to-2 new file mode 100755 index 000000000..3a76fc0e0 --- /dev/null +++ b/src/migration-scripts/conntrack-sync/1-to-2 @@ -0,0 +1,61 @@ +#!/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/>. + +# VyOS 1.2 crux allowed configuring a lower or upper case loglevel. This +# is no longer supported as the input data is validated and will lead to +# an error. If user specifies an upper case logleve, make it lowercase + +from sys import argv +from sys import exit + +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 = ['service', 'conntrack-sync'] +config = ConfigTree(config_file) + +if not config.exists(base): + # Nothing to do + exit(0) +else: + base_accept_proto = base + ['accept-protocol'] + if config.exists(base_accept_proto): + tmp = config.return_value(base_accept_proto) + config.delete(base_accept_proto) + for protocol in tmp.split(','): + config.set(base_accept_proto, value=protocol, replace=False) + + base_ignore_addr = base + ['ignore-address', 'ipv4'] + if config.exists(base_ignore_addr): + tmp = config.return_values(base_ignore_addr) + config.delete(base_ignore_addr) + for address in tmp: + config.set(base + ['ignore-address'], value=address, replace=False) + + 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) diff --git a/src/validators/ipv4 b/src/validators/ipv4 new file mode 100755 index 000000000..53face090 --- /dev/null +++ b/src/validators/ipv4 @@ -0,0 +1,3 @@ +#!/bin/sh + +ipaddrcheck --is-ipv4 $1 diff --git a/src/validators/ipv4-multicast b/src/validators/ipv4-multicast new file mode 100755 index 000000000..e5cbc9532 --- /dev/null +++ b/src/validators/ipv4-multicast @@ -0,0 +1,3 @@ +#!/bin/sh + +ipaddrcheck --is-ipv4-multicast $1 diff --git a/src/validators/ipv6-multicast b/src/validators/ipv6-multicast new file mode 100755 index 000000000..66cd90c9c --- /dev/null +++ b/src/validators/ipv6-multicast @@ -0,0 +1,3 @@ +#!/bin/sh + +ipaddrcheck --is-ipv6-multicast $1 |