diff options
-rw-r--r-- | data/templates/conserver/conserver.conf.j2 | 3 | ||||
-rw-r--r-- | data/templates/ipsec/ios_profile.j2 | 2 | ||||
-rw-r--r-- | interface-definitions/include/firewall/common-rule.xml.i | 16 | ||||
-rw-r--r-- | interface-definitions/service-console-server.xml.in | 8 | ||||
-rw-r--r-- | interface-definitions/xml-component-version.xml.in | 1 | ||||
-rw-r--r-- | op-mode-definitions/clear-session.xml.in | 16 | ||||
-rw-r--r-- | op-mode-definitions/connect.xml.in | 1 | ||||
-rw-r--r-- | op-mode-definitions/show-console-server.xml.in | 2 | ||||
-rw-r--r-- | op-mode-definitions/show-interfaces-pppoe.xml.in | 2 | ||||
-rw-r--r-- | python/vyos/firewall.py | 8 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_firewall.py | 14 | ||||
-rwxr-xr-x | src/completion/list_consoles.sh | 4 | ||||
-rwxr-xr-x | src/conf_mode/service_console-server.py | 7 | ||||
-rwxr-xr-x | src/op_mode/nat.py | 11 |
14 files changed, 84 insertions, 11 deletions
diff --git a/data/templates/conserver/conserver.conf.j2 b/data/templates/conserver/conserver.conf.j2 index 1823657d7..ffd29389d 100644 --- a/data/templates/conserver/conserver.conf.j2 +++ b/data/templates/conserver/conserver.conf.j2 @@ -25,6 +25,9 @@ console {{ key }} { baud {{ value.speed }}; parity {{ value.parity }}; options {{ "!" if value.stop_bits == "1" }}cstopb; +{% if value.alias is vyos_defined %} + aliases "{{ value.alias }}"; +{% endif %} } {% endfor %} diff --git a/data/templates/ipsec/ios_profile.j2 b/data/templates/ipsec/ios_profile.j2 index c8e17729a..eb74924b8 100644 --- a/data/templates/ipsec/ios_profile.j2 +++ b/data/templates/ipsec/ios_profile.j2 @@ -41,7 +41,7 @@ <!-- Remote identity, can be a FQDN, a userFQDN, an IP or (theoretically) a certificate's subject DN. Can't be empty. IMPORTANT: DNs are currently not handled correctly, they are always sent as identities of type FQDN --> <key>RemoteIdentifier</key> - <string>{{ authentication.id if authentication.id is vyos_defined else 'VyOS' }}</string> + <string>{{ authentication.local_id if authentication.local_id is vyos_defined else 'VyOS' }}</string> <!-- Local IKE identity, same restrictions as above. If it is empty the client's IP address will be used --> <key>LocalIdentifier</key> <string></string> diff --git a/interface-definitions/include/firewall/common-rule.xml.i b/interface-definitions/include/firewall/common-rule.xml.i index 079864122..a4f66f5cb 100644 --- a/interface-definitions/include/firewall/common-rule.xml.i +++ b/interface-definitions/include/firewall/common-rule.xml.i @@ -26,6 +26,14 @@ </leafNode> </children> </node> +<leafNode name="inbound-interface"> + <properties> + <help>Match inbound-interface</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + </properties> +</leafNode> <node name="ipsec"> <properties> <help>Inbound IPsec packets</help> @@ -122,6 +130,14 @@ </leafNode> </children> </node> +<leafNode name="outbound-interface"> + <properties> + <help>Match outbound-interface</help> + <completionHelp> + <script>${vyos_completion_dir}/list_interfaces.py</script> + </completionHelp> + </properties> +</leafNode> <leafNode name="protocol"> <properties> <help>Protocol to match (protocol name, number, or "all")</help> diff --git a/interface-definitions/service-console-server.xml.in b/interface-definitions/service-console-server.xml.in index e9591ad87..fb71538dd 100644 --- a/interface-definitions/service-console-server.xml.in +++ b/interface-definitions/service-console-server.xml.in @@ -28,6 +28,14 @@ </properties> <children> #include <include/interface/description.xml.i> + <leafNode name="alias"> + <properties> + <help>Human-readable name for this console</help> + <constraint> + <regex>[-_a-zA-Z0-9.]{1,128}</regex> + </constraint> + </properties> + </leafNode> <leafNode name="speed"> <properties> <help>Serial port baud rate</help> diff --git a/interface-definitions/xml-component-version.xml.in b/interface-definitions/xml-component-version.xml.in index cf86f83d6..914e3bc69 100644 --- a/interface-definitions/xml-component-version.xml.in +++ b/interface-definitions/xml-component-version.xml.in @@ -14,6 +14,7 @@ #include <include/version/flow-accounting-version.xml.i> #include <include/version/https-version.xml.i> #include <include/version/interfaces-version.xml.i> + #include <include/version/ids-version.xml.i> #include <include/version/ipoe-server-version.xml.i> #include <include/version/ipsec-version.xml.i> #include <include/version/isis-version.xml.i> diff --git a/op-mode-definitions/clear-session.xml.in b/op-mode-definitions/clear-session.xml.in new file mode 100644 index 000000000..bfafe6312 --- /dev/null +++ b/op-mode-definitions/clear-session.xml.in @@ -0,0 +1,16 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="clear"> + <children> + <tagNode name="session"> + <properties> + <help>Terminate TTY or PTS user session</help> + <completionHelp> + <script>who | awk '{print $2}'</script> + </completionHelp> + </properties> + <command>sudo pkill -9 -t $3</command> + </tagNode> + </children> + </node> +</interfaceDefinition> diff --git a/op-mode-definitions/connect.xml.in b/op-mode-definitions/connect.xml.in index 8f19eac70..d0c93195c 100644 --- a/op-mode-definitions/connect.xml.in +++ b/op-mode-definitions/connect.xml.in @@ -10,6 +10,7 @@ <help>Connect to device attached to serial console server</help> <completionHelp> <path>service console-server device</path> + <script>${vyos_completion_dir}/list_consoles.sh</script> </completionHelp> </properties> <command>/usr/bin/console "$3"</command> diff --git a/op-mode-definitions/show-console-server.xml.in b/op-mode-definitions/show-console-server.xml.in index 253d15498..eae6fd536 100644 --- a/op-mode-definitions/show-console-server.xml.in +++ b/op-mode-definitions/show-console-server.xml.in @@ -8,7 +8,7 @@ <properties> <help>Show log for serial console server</help> </properties> - <command>/usr/bin/journalctl --unit conserver-server.service</command> + <command>journalctl --no-hostname --boot --follow --unit conserver-server.service</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/show-interfaces-pppoe.xml.in b/op-mode-definitions/show-interfaces-pppoe.xml.in index 767836abf..09608bc04 100644 --- a/op-mode-definitions/show-interfaces-pppoe.xml.in +++ b/op-mode-definitions/show-interfaces-pppoe.xml.in @@ -17,7 +17,7 @@ <properties> <help>Show specified PPPoE interface log</help> </properties> - <command>/usr/bin/journalctl --unit "ppp@$4".service</command> + <command>journalctl --no-hostname --boot --follow --unit "ppp@$4".service</command> </leafNode> <leafNode name="statistics"> <properties> diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py index f9b7222fd..4075e55b0 100644 --- a/python/vyos/firewall.py +++ b/python/vyos/firewall.py @@ -248,6 +248,14 @@ def parse_rule(rule_conf, fw_name, rule_id, ip_name): value = rule_conf['hop_limit'][op] output.append(f'ip6 hoplimit {operator} {value}') + if 'inbound_interface' in rule_conf: + iiface = rule_conf['inbound_interface'] + output.append(f'iifname {iiface}') + + if 'outbound_interface' in rule_conf: + oiface = rule_conf['outbound_interface'] + output.append(f'oifname {oiface}') + if 'ttl' in rule_conf: operators = {'eq': '==', 'gt': '>', 'lt': '<'} for op, operator in operators.items(): diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py index 4b2cf9864..821925bcd 100755 --- a/smoketest/scripts/cli/test_firewall.py +++ b/smoketest/scripts/cli/test_firewall.py @@ -209,8 +209,10 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'name', name, 'rule', '5', 'protocol', 'tcp']) self.cli_set(['firewall', 'name', name, 'rule', '5', 'tcp', 'flags', 'syn']) self.cli_set(['firewall', 'name', name, 'rule', '5', 'tcp', 'mss', mss_range]) + self.cli_set(['firewall', 'name', name, 'rule', '5', 'inbound-interface', interface]) self.cli_set(['firewall', 'name', name, 'rule', '6', 'action', 'return']) self.cli_set(['firewall', 'name', name, 'rule', '6', 'protocol', 'gre']) + self.cli_set(['firewall', 'name', name, 'rule', '6', 'outbound-interface', interface]) self.cli_set(['firewall', 'interface', interface, 'in', 'name', name]) @@ -223,8 +225,8 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): ['tcp dport 22', 'limit rate 5/minute', 'return'], ['log prefix "[smoketest-default-D]"','smoketest default-action', 'drop'], ['tcp dport 22', 'add @RECENT_smoketest_4 { ip saddr limit rate over 10/minute burst 10 packets }', 'drop'], - ['tcp flags & syn == syn', f'tcp option maxseg size {mss_range}'], - ['meta l4proto gre', 'return'] + ['tcp flags & syn == syn', f'tcp option maxseg size {mss_range}', f'iifname "{interface}"'], + ['meta l4proto gre', f'oifname "{interface}"', 'return'] ] self.verify_nftables(nftables_search, 'ip vyos_filter') @@ -288,9 +290,11 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'ipv6-name', name, 'rule', '2', 'action', 'reject']) self.cli_set(['firewall', 'ipv6-name', name, 'rule', '2', 'protocol', 'tcp_udp']) self.cli_set(['firewall', 'ipv6-name', name, 'rule', '2', 'destination', 'port', '8888']) + self.cli_set(['firewall', 'ipv6-name', name, 'rule', '2', 'inbound-interface', interface]) self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'action', 'return']) self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'protocol', 'gre']) + self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'outbound-interface', interface]) self.cli_set(['firewall', 'interface', interface, 'in', 'ipv6-name', name]) @@ -299,9 +303,9 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): nftables_search = [ [f'iifname "{interface}"', f'jump NAME6_{name}'], ['saddr 2002::1', 'daddr 2002::1:1', 'log prefix "[v6-smoketest-1-A]" level crit', 'return'], - ['meta l4proto { tcp, udp }', 'th dport 8888', 'reject'], - ['smoketest default-action', f'log prefix "[{name}-default-D]"', 'drop'], - ['meta l4proto gre', 'return'] + ['meta l4proto { tcp, udp }', 'th dport 8888', f'iifname "{interface}"', 'reject'], + ['meta l4proto gre', f'oifname "{interface}"', 'return'], + ['smoketest default-action', f'log prefix "[{name}-default-D]"', 'drop'] ] self.verify_nftables(nftables_search, 'ip6 vyos_filter') diff --git a/src/completion/list_consoles.sh b/src/completion/list_consoles.sh new file mode 100755 index 000000000..52278c4cb --- /dev/null +++ b/src/completion/list_consoles.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +# For lines like `aliases "foo";`, regex matches everything between the quotes +grep -oP '(?<=aliases ").+(?=";)' /run/conserver/conserver.cf
\ No newline at end of file diff --git a/src/conf_mode/service_console-server.py b/src/conf_mode/service_console-server.py index a2e411e49..ee4fe42ab 100755 --- a/src/conf_mode/service_console-server.py +++ b/src/conf_mode/service_console-server.py @@ -61,6 +61,7 @@ def verify(proxy): if not proxy: return None + aliases = [] processes = process_iter(['name', 'cmdline']) if 'device' in proxy: for device, device_config in proxy['device'].items(): @@ -75,6 +76,12 @@ def verify(proxy): if 'ssh' in device_config and 'port' not in device_config['ssh']: raise ConfigError(f'Port "{device}" requires SSH port to be set!') + if 'alias' in device_config: + if device_config['alias'] in aliases: + raise ConfigError("Console aliases must be unique") + else: + aliases.append(device_config['alias']) + return None def generate(proxy): diff --git a/src/op_mode/nat.py b/src/op_mode/nat.py index a0496dedb..845dbbb2c 100755 --- a/src/op_mode/nat.py +++ b/src/op_mode/nat.py @@ -109,7 +109,7 @@ def _get_formatted_output_rules(data, direction, family): if jmespath.search('rule.expr[*].match.left.meta', rule) else 'any' for index, match in enumerate(jmespath.search('rule.expr[*].match', rule)): if 'payload' in match['left']: - if 'prefix' in match['right'] or 'set' in match['right']: + if isinstance(match['right'], dict) and ('prefix' in match['right'] or 'set' in match['right']): # Merge dict src/dst l3_l4 parameters my_dict = {**match['left']['payload'], **match['right']} my_dict['op'] = match['op'] @@ -136,10 +136,15 @@ def _get_formatted_output_rules(data, direction, family): dport = my_dict.get('set') dport = ','.join(map(str, dport)) else: - if jmespath.search('left.payload.field', match) == 'saddr': + field = jmespath.search('left.payload.field', match) + if field == 'saddr': saddr = match.get('right') - if jmespath.search('left.payload.field', match) == 'daddr': + elif field == 'daddr': daddr = match.get('right') + elif field == 'sport': + sport = match.get('right') + elif field == 'dport': + dport = match.get('right') else: saddr = '::/0' if family == 'inet6' else '0.0.0.0/0' daddr = '::/0' if family == 'inet6' else '0.0.0.0/0' |