diff options
-rw-r--r-- | data/templates/accel-ppp/pppoe.config.tmpl | 3 | ||||
-rw-r--r-- | data/templates/dhcp-server/dhcpdv6.conf.tmpl | 3 | ||||
-rw-r--r-- | data/templates/ipsec/swanctl.conf.tmpl | 2 | ||||
-rw-r--r-- | data/templates/ipsec/swanctl/peer.tmpl | 10 | ||||
-rw-r--r-- | interface-definitions/dhcpv6-server.xml.in | 12 | ||||
-rw-r--r-- | interface-definitions/include/accel-ppp/ppp-interface-cache.xml.i | 14 | ||||
-rw-r--r-- | interface-definitions/service_pppoe-server.xml.in | 1 | ||||
-rw-r--r-- | python/vyos/ifconfig/vti.py | 6 | ||||
-rw-r--r-- | python/vyos/util.py | 10 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_protocols_bgp.py | 20 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_service_dhcpv6-server.py | 3 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_service_pppoe-server.py | 7 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_vpn_ipsec.py | 260 | ||||
-rwxr-xr-x | src/completion/list_dumpable_interfaces.py | 2 | ||||
-rwxr-xr-x | src/conf_mode/interfaces-vti.py | 31 | ||||
-rwxr-xr-x | src/conf_mode/protocols_bgp.py | 4 | ||||
-rwxr-xr-x | src/conf_mode/vpn_ipsec.py | 18 |
17 files changed, 222 insertions, 184 deletions
diff --git a/data/templates/accel-ppp/pppoe.config.tmpl b/data/templates/accel-ppp/pppoe.config.tmpl index 05ac31d18..238e7ee15 100644 --- a/data/templates/accel-ppp/pppoe.config.tmpl +++ b/data/templates/accel-ppp/pppoe.config.tmpl @@ -95,6 +95,9 @@ ipv6-accept-peer-intf-id={{ "1" if ppp_options.ipv6_accept_peer_intf_id is defin {% endif %} {# MTU #} mtu={{ mtu }} +{% if ppp_options.interface_cache is defined and ppp_options.interface_cache is not none %} +unit-cache={{ ppp_options.interface_cache }} +{% endif %} [pppoe] verbose=1 diff --git a/data/templates/dhcp-server/dhcpdv6.conf.tmpl b/data/templates/dhcp-server/dhcpdv6.conf.tmpl index 8d653ff72..45d629928 100644 --- a/data/templates/dhcp-server/dhcpdv6.conf.tmpl +++ b/data/templates/dhcp-server/dhcpdv6.conf.tmpl @@ -107,6 +107,9 @@ shared-network {{ network | replace('_','-') }} { {% if host_config.ipv6_address is defined and host_config.ipv6_address is not none %} fixed-address6 {{ host_config.ipv6_address }}; {% endif %} +{% if host_config.ipv6_prefix is defined and host_config.ipv6_prefix is not none %} + fixed-prefix6 {{ host_config.ipv6_prefix }}; +{% endif %} } {% endfor %} {% endif %} diff --git a/data/templates/ipsec/swanctl.conf.tmpl b/data/templates/ipsec/swanctl.conf.tmpl index 9e629b176..0ff08ee15 100644 --- a/data/templates/ipsec/swanctl.conf.tmpl +++ b/data/templates/ipsec/swanctl.conf.tmpl @@ -18,7 +18,7 @@ connections { {% set peer_ike = ike_group[peer_conf.ike_group] %} {% set peer_esp = esp_group[peer_conf.default_esp_group] if peer_conf.default_esp_group is defined else None %} {% set auth_type = authby[peer_conf.authentication.mode] %} -{{ peer_tmpl.conn(peer_conn_name, peer, peer_conf, peer_ike, peer_esp, ciphers, esp_group, auth_type, marks) }} +{{ peer_tmpl.conn(peer_conn_name, peer, peer_conf, peer_ike, peer_esp, ciphers, esp_group, auth_type) }} {% endfor %} {% endif %} } diff --git a/data/templates/ipsec/swanctl/peer.tmpl b/data/templates/ipsec/swanctl/peer.tmpl index 36cb1abfb..c97ac1f67 100644 --- a/data/templates/ipsec/swanctl/peer.tmpl +++ b/data/templates/ipsec/swanctl/peer.tmpl @@ -1,4 +1,4 @@ -{% macro conn(name, peer, peer_conf, ike, esp, ciphers, esp_group, auth_type, marks) %} +{% macro conn(name, peer, peer_conf, ike, esp, ciphers, esp_group, auth_type) %} peer_{{ name }} { proposals = {{ ciphers.ike[peer_conf.ike_group] }} version = {{ ike['key_exchange'][4:] if "key_exchange" in ike else "0" }} @@ -61,8 +61,8 @@ local_ts = 0.0.0.0/0,::/0 remote_ts = 0.0.0.0/0,::/0 updown = "/etc/ipsec.d/vti-up-down {{ peer_conf.vti.bind }} {{ peer_conf.dhcp_interface if peer_conf.dhcp_interface is defined else 'no' }}" - mark_in = {{ marks[peer_conf.vti.bind] }} - mark_out = {{ marks[peer_conf.vti.bind] }} + if_id_in = {{ peer_conf.vti.bind | replace('vti', '') }} + if_id_out = {{ peer_conf.vti.bind | replace('vti', '') }} ipcomp = {{ 'yes' if "compression" in vti_esp and vti_esp.compression == 'enable' else 'no' }} mode = {{ vti_esp.mode if "mode" in vti_esp else "tunnel" }} {% if peer[0:1] == '@' %} @@ -117,8 +117,8 @@ {% endif %} {% if peer_conf.vti is defined and peer_conf.vti.bind is defined %} updown = "/etc/ipsec.d/vti-up-down {{ peer_conf.vti.bind }} {{ peer_conf.dhcp_interface if peer_conf.dhcp_interface is defined else 'no' }}" - mark_in = {{ marks[peer_conf.vti.bind] }} - mark_out = {{ marks[peer_conf.vti.bind] }} + if_id_in = {{ peer_conf.vti.bind | replace('vti', '') }} + if_id_out = {{ peer_conf.vti.bind | replace('vti', '') }} {% endif %} } {% if tunnel_conf.passthrough is defined and tunnel_conf.passthrough %} diff --git a/interface-definitions/dhcpv6-server.xml.in b/interface-definitions/dhcpv6-server.xml.in index a3cca06da..5d6c64685 100644 --- a/interface-definitions/dhcpv6-server.xml.in +++ b/interface-definitions/dhcpv6-server.xml.in @@ -360,6 +360,18 @@ </constraint> </properties> </leafNode> + <leafNode name="ipv6-prefix"> + <properties> + <help>Client IPv6 prefix for this static mapping</help> + <valueHelp> + <format>ipv6net</format> + <description>IPv6 prefix for this static mapping</description> + </valueHelp> + <constraint> + <validator name="ipv6-prefix"/> + </constraint> + </properties> + </leafNode> </children> </tagNode> </children> diff --git a/interface-definitions/include/accel-ppp/ppp-interface-cache.xml.i b/interface-definitions/include/accel-ppp/ppp-interface-cache.xml.i new file mode 100644 index 000000000..9f223d7ed --- /dev/null +++ b/interface-definitions/include/accel-ppp/ppp-interface-cache.xml.i @@ -0,0 +1,14 @@ +<!-- include start from accel-ppp/ppp-interface-cache.xml.i --> +<leafNode name="interface-cache"> + <properties> + <help>PPP interface cache</help> + <valueHelp> + <format>1-256000</format> + <description>Count of interfaces to keep in cache</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-256000"/> + </constraint> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/service_pppoe-server.xml.in b/interface-definitions/service_pppoe-server.xml.in index 788683868..7b96b5692 100644 --- a/interface-definitions/service_pppoe-server.xml.in +++ b/interface-definitions/service_pppoe-server.xml.in @@ -164,6 +164,7 @@ #include <include/accel-ppp/ppp-mppe.xml.i> #include <include/accel-ppp/lcp-echo-interval-failure.xml.i> #include <include/accel-ppp/lcp-echo-timeout.xml.i> + #include <include/accel-ppp/ppp-interface-cache.xml.i> <leafNode name="ipv4"> <properties> <help>IPv4 (IPCP) negotiation algorithm</help> diff --git a/python/vyos/ifconfig/vti.py b/python/vyos/ifconfig/vti.py index 9eafcd11b..a217d28ea 100644 --- a/python/vyos/ifconfig/vti.py +++ b/python/vyos/ifconfig/vti.py @@ -33,13 +33,11 @@ class VTIIf(Interface): # - https://man7.org/linux/man-pages/man8/ip-link.8.html # - https://man7.org/linux/man-pages/man8/ip-tunnel.8.html mapping = { - 'source_address' : 'local', 'source_interface' : 'dev', - 'remote' : 'remote', - 'key' : 'key', } - cmd = 'ip link add {ifname} type vti' + if_id = self.ifname.lstrip('vti') + cmd = f'ip link add {self.ifname} type xfrm if_id {if_id}' for vyos_key, iproute2_key in mapping.items(): # dict_search will return an empty dict "{}" for valueless nodes like # "parameters.nolearning" - thus we need to test the nodes existence diff --git a/python/vyos/util.py b/python/vyos/util.py index c3bf481ea..65c9c2f45 100644 --- a/python/vyos/util.py +++ b/python/vyos/util.py @@ -231,8 +231,14 @@ def copy_file(source, destination, mkdstdir=False, user=None, group=None): dirname = os.path.dirname(destination) if not os.path.isdir(dirname): makedir(dirname, user, group) - - shutil.copyfile(source, destination) + try: + filename = os.path.basename(source) + if not destination.endswith('/'): + destination + '/' + shutil.copyfile(source, destination + filename) + except shutil.SameFileError: + # We don't care if we copy the same file again + pass chown(destination, user, group) def read_json(fname, defaultonfailure=None): diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py index c51d83875..a1b3356ce 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -674,5 +674,25 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase): self.assertIn(f' bgp confederation identifier {confed_id}', frrconfig) self.assertIn(f' bgp confederation peers {confed_asns}', frrconfig) + + def test_bgp_12_v6_link_local(self): + remote_asn = str(int(ASN) + 10) + interface = 'eth0' + + self.cli_set(base_path + ['local-as', ASN]) + self.cli_set(base_path + ['neighbor', interface, 'address-family', 'ipv6-unicast']) + self.cli_set(base_path + ['neighbor', interface, 'interface', 'v6only', 'remote-as', remote_asn]) + + # commit changes + self.cli_commit() + + # Verify FRR bgpd configuration + frrconfig = self.getFRRconfig(f'router bgp {ASN}') + self.assertIn(f'router bgp {ASN}', frrconfig) + self.assertIn(f' neighbor {interface} interface v6only remote-as {remote_asn}', frrconfig) + self.assertIn(f' address-family ipv6 unicast', frrconfig) + self.assertIn(f' neighbor {interface} activate', frrconfig) + self.assertIn(f' exit-address-family', frrconfig) + if __name__ == '__main__': unittest.main(verbosity=2)
\ No newline at end of file diff --git a/smoketest/scripts/cli/test_service_dhcpv6-server.py b/smoketest/scripts/cli/test_service_dhcpv6-server.py index a939aa003..3f9564e59 100755 --- a/smoketest/scripts/cli/test_service_dhcpv6-server.py +++ b/smoketest/scripts/cli/test_service_dhcpv6-server.py @@ -86,6 +86,7 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): cid = '00:01:00:01:12:34:56:78:aa:bb:cc:dd:ee:{}'.format(client_base) self.cli_set(pool + ['static-mapping', client, 'identifier', cid]) self.cli_set(pool + ['static-mapping', client, 'ipv6-address', inc_ip(subnet, client_base)]) + self.cli_set(pool + ['static-mapping', client, 'ipv6-prefix', inc_ip(subnet, client_base << 64) + '/64']) client_base += 1 # commit changes @@ -114,8 +115,10 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase): for client in ['client1', 'client2', 'client3']: cid = '00:01:00:01:12:34:56:78:aa:bb:cc:dd:ee:{}'.format(client_base) ip = inc_ip(subnet, client_base) + prefix = inc_ip(subnet, client_base << 64) + '/64' self.assertIn(f'host {shared_net_name}_{client}' + ' {', config) self.assertIn(f'fixed-address6 {ip};', config) + self.assertIn(f'fixed-prefix6 {prefix};', config) self.assertIn(f'host-identifier option dhcp6.client-id {cid};', config) client_base += 1 diff --git a/smoketest/scripts/cli/test_service_pppoe-server.py b/smoketest/scripts/cli/test_service_pppoe-server.py index 2b11ee362..51cc098ef 100755 --- a/smoketest/scripts/cli/test_service_pppoe-server.py +++ b/smoketest/scripts/cli/test_service_pppoe-server.py @@ -91,6 +91,10 @@ class TestServicePPPoEServer(BasicAccelPPPTest.TestCase): mru = '9000' self.set(['ppp-options', 'mru', mru]) + # interface-cache + interface_cache = '128000' + self.set(['ppp-options', 'interface-cache', interface_cache]) + # commit changes self.cli_commit() @@ -113,6 +117,9 @@ class TestServicePPPoEServer(BasicAccelPPPTest.TestCase): # check other settings self.assertEqual(conf['connlimit']['limit'], '20/min') + # check interface-cache + self.assertEqual(conf['ppp']['unit-cache'], interface_cache) + # Check for running process self.assertTrue(process_named_running(self._process_name)) diff --git a/smoketest/scripts/cli/test_vpn_ipsec.py b/smoketest/scripts/cli/test_vpn_ipsec.py index b27ed3ca5..fee4d6ade 100755 --- a/smoketest/scripts/cli/test_vpn_ipsec.py +++ b/smoketest/scripts/cli/test_vpn_ipsec.py @@ -30,7 +30,17 @@ base_path = ['vpn', 'ipsec'] dhcp_waiting_file = '/tmp/ipsec_dhcp_waiting' swanctl_file = '/etc/swanctl/swanctl.conf' +peer_ip = '203.0.113.45' +interface = 'eth1' +vif = '100' +esp_group = 'MyESPGroup' +ike_group = 'MyIKEGroup' +secret = 'MYSECRETKEY' + class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): + def setUp(self): + self.cli_set(base_path + ['ipsec-interfaces', 'interface', f'{interface}.{vif}']) + def tearDown(self): self.cli_delete(base_path) self.cli_delete(nhrp_path) @@ -40,34 +50,31 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): self.cli_commit() def test_dhcp_fail_handling(self): - self.cli_delete(ethernet_path) - self.cli_delete(base_path) - # Interface for dhcp-interface - self.cli_set(ethernet_path + ['eth0', 'vif', '100', 'address', 'dhcp']) # Use VLAN to avoid getting IP from qemu dhcp server + self.cli_set(ethernet_path + [interface, 'vif', vif, 'address', 'dhcp']) # Use VLAN to avoid getting IP from qemu dhcp server # Set IKE/ESP Groups - self.cli_set(base_path + ["esp-group", "MyESPGroup", "proposal", "1", "encryption", "aes128"]) - self.cli_set(base_path + ["esp-group", "MyESPGroup", "proposal", "1", "hash", "sha1"]) - self.cli_set(base_path + ["ike-group", "MyIKEGroup", "proposal", "1", "dh-group", "2"]) - self.cli_set(base_path + ["ike-group", "MyIKEGroup", "proposal", "1", "encryption", "aes128"]) - self.cli_set(base_path + ["ike-group", "MyIKEGroup", "proposal", "1", "hash", "sha1"]) + self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '1', 'encryption', 'aes128']) + self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '1', 'hash', 'sha1']) + self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'dh-group', '2']) + self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'encryption', 'aes128']) + self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'hash', 'sha1']) # Site to site - self.cli_set(base_path + ["ipsec-interfaces", "interface", "eth0.100"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "authentication", "mode", "pre-shared-secret"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "authentication", "pre-shared-secret", "MYSECRETKEY"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "ike-group", "MyIKEGroup"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "default-esp-group", "MyESPGroup"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "dhcp-interface", "eth0.100"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "protocol", "gre"]) + peer_base_path = base_path + ['site-to-site', 'peer', peer_ip] + self.cli_set(peer_base_path + ['authentication', 'mode', 'pre-shared-secret']) + self.cli_set(peer_base_path + ['authentication', 'pre-shared-secret', secret]) + self.cli_set(peer_base_path + ['ike-group', ike_group]) + self.cli_set(peer_base_path + ['default-esp-group', esp_group]) + self.cli_set(peer_base_path + ['dhcp-interface', f'{interface}.{vif}']) + self.cli_set(peer_base_path + ['tunnel', '1', 'protocol', 'gre']) self.cli_commit() self.assertTrue(os.path.exists(dhcp_waiting_file)) dhcp_waiting = read_file(dhcp_waiting_file) - self.assertIn('eth0.100', dhcp_waiting) # Ensure dhcp-failed interface was added for dhclient hook + self.assertIn(f'{interface}.{vif}', dhcp_waiting) # Ensure dhcp-failed interface was added for dhclient hook self.assertTrue(process_named_running('charon')) # Commit should've still succeeded and launched charon @@ -75,46 +82,46 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): self.cli_delete(base_path) # IKE/ESP Groups - self.cli_set(base_path + ["esp-group", "MyESPGroup", "proposal", "1", "encryption", "aes128"]) - self.cli_set(base_path + ["esp-group", "MyESPGroup", "proposal", "1", "hash", "sha1"]) - self.cli_set(base_path + ["ike-group", "MyIKEGroup", "proposal", "1", "dh-group", "2"]) - self.cli_set(base_path + ["ike-group", "MyIKEGroup", "proposal", "1", "encryption", "aes128"]) - self.cli_set(base_path + ["ike-group", "MyIKEGroup", "proposal", "1", "hash", "sha1"]) - self.cli_set(base_path + ["ike-group", "MyIKEGroup", "key-exchange", "ikev2"]) + self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '1', 'encryption', 'aes128']) + self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '1', 'hash', 'sha1']) + self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'dh-group', '2']) + self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'encryption', 'aes128']) + self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'hash', 'sha1']) + self.cli_set(base_path + ['ike-group', ike_group, 'key-exchange', 'ikev2']) # Site to site - self.cli_set(base_path + ["ipsec-interfaces", "interface", "eth0"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "authentication", "mode", "pre-shared-secret"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "authentication", "pre-shared-secret", "MYSECRETKEY"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "ike-group", "MyIKEGroup"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "default-esp-group", "MyESPGroup"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "local-address", "192.0.2.10"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "protocol", "tcp"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "local", "prefix", "172.16.10.0/24"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "local", "prefix", "172.16.11.0/24"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "local", "port", "443"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "remote", "prefix", "172.17.10.0/24"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "remote", "prefix", "172.17.11.0/24"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "remote", "port", "443"]) + peer_base_path = base_path + ['site-to-site', 'peer', peer_ip] + self.cli_set(peer_base_path + ['authentication', 'mode', 'pre-shared-secret']) + self.cli_set(peer_base_path + ['authentication', 'pre-shared-secret', secret]) + self.cli_set(peer_base_path + ['ike-group', ike_group]) + self.cli_set(peer_base_path + ['default-esp-group', esp_group]) + self.cli_set(peer_base_path + ['local-address', '192.0.2.10']) + self.cli_set(peer_base_path + ['tunnel', '1', 'protocol', 'tcp']) + self.cli_set(peer_base_path + ['tunnel', '1', 'local', 'prefix', '172.16.10.0/24']) + self.cli_set(peer_base_path + ['tunnel', '1', 'local', 'prefix', '172.16.11.0/24']) + self.cli_set(peer_base_path + ['tunnel', '1', 'local', 'port', '443']) + self.cli_set(peer_base_path + ['tunnel', '1', 'remote', 'prefix', '172.17.10.0/24']) + self.cli_set(peer_base_path + ['tunnel', '1', 'remote', 'prefix', '172.17.11.0/24']) + self.cli_set(peer_base_path + ['tunnel', '1', 'remote', 'port', '443']) self.cli_commit() swanctl_conf_lines = [ - 'version = 2', - 'auth = psk', - 'proposals = aes128-sha1-modp1024', - 'esp_proposals = aes128-sha1-modp1024', - 'local_addrs = 192.0.2.10 # dhcp:no', - 'remote_addrs = 203.0.113.45', - 'mode = tunnel', - 'local_ts = 172.16.10.0/24[tcp/443],172.16.11.0/24[tcp/443]', - 'remote_ts = 172.17.10.0/24[tcp/443],172.17.11.0/24[tcp/443]' + f'version = 2', + f'auth = psk', + f'proposals = aes128-sha1-modp1024', + f'esp_proposals = aes128-sha1-modp1024', + f'local_addrs = 192.0.2.10 # dhcp:no', + f'remote_addrs = {peer_ip}', + f'mode = tunnel', + f'local_ts = 172.16.10.0/24[tcp/443],172.16.11.0/24[tcp/443]', + f'remote_ts = 172.17.10.0/24[tcp/443],172.17.11.0/24[tcp/443]' ] swanctl_secrets_lines = [ - 'id-local = 192.0.2.10 # dhcp:no', - 'id-remote = 203.0.113.45', - 'secret = "MYSECRETKEY"' + f'id-local = 192.0.2.10 # dhcp:no', + f'id-remote = {peer_ip}', + f'secret = "{secret}"' ] tmp_swanctl_conf = read_file(swanctl_file) @@ -129,55 +136,54 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): self.assertTrue(process_named_running('charon')) def test_site_to_site_vti(self): - self.cli_delete(base_path) - self.cli_delete(vti_path) + vti = 'vti10' # VTI interface - self.cli_set(vti_path + ["vti10", "address", "10.1.1.1/24"]) + self.cli_set(vti_path + [vti, 'address', '10.1.1.1/24']) # IKE/ESP Groups - self.cli_set(base_path + ["esp-group", "MyESPGroup", "proposal", "1", "encryption", "aes128"]) - self.cli_set(base_path + ["esp-group", "MyESPGroup", "proposal", "1", "hash", "sha1"]) - self.cli_set(base_path + ["ike-group", "MyIKEGroup", "proposal", "1", "dh-group", "2"]) - self.cli_set(base_path + ["ike-group", "MyIKEGroup", "proposal", "1", "encryption", "aes128"]) - self.cli_set(base_path + ["ike-group", "MyIKEGroup", "proposal", "1", "hash", "sha1"]) - self.cli_set(base_path + ["ike-group", "MyIKEGroup", "key-exchange", "ikev2"]) + self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '1', 'encryption', 'aes128']) + self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '1', 'hash', 'sha1']) + self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'dh-group', '2']) + self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'encryption', 'aes128']) + self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'hash', 'sha1']) + self.cli_set(base_path + ['ike-group', ike_group, 'key-exchange', 'ikev2']) # Site to site - self.cli_set(base_path + ["ipsec-interfaces", "interface", "eth0"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "authentication", "mode", "pre-shared-secret"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "authentication", "pre-shared-secret", "MYSECRETKEY"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "ike-group", "MyIKEGroup"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "default-esp-group", "MyESPGroup"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "local-address", "192.0.2.10"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "local", "prefix", "172.16.10.0/24"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "local", "prefix", "172.16.11.0/24"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "remote", "prefix", "172.17.10.0/24"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "remote", "prefix", "172.17.11.0/24"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "vti", "bind", "vti10"]) - self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "vti", "esp-group", "MyESPGroup"]) + peer_base_path = base_path + ['site-to-site', 'peer', peer_ip] + self.cli_set(peer_base_path + ['authentication', 'mode', 'pre-shared-secret']) + self.cli_set(peer_base_path + ['authentication', 'pre-shared-secret', secret]) + self.cli_set(peer_base_path + ['ike-group', ike_group]) + self.cli_set(peer_base_path + ['default-esp-group', esp_group]) + self.cli_set(peer_base_path + ['local-address', '192.0.2.10']) + self.cli_set(peer_base_path + ['tunnel', '1', 'local', 'prefix', '172.16.10.0/24']) + self.cli_set(peer_base_path + ['tunnel', '1', 'local', 'prefix', '172.16.11.0/24']) + self.cli_set(peer_base_path + ['tunnel', '1', 'remote', 'prefix', '172.17.10.0/24']) + self.cli_set(peer_base_path + ['tunnel', '1', 'remote', 'prefix', '172.17.11.0/24']) + self.cli_set(peer_base_path + ['vti', 'bind', vti]) + self.cli_set(peer_base_path + ['vti', 'esp-group', esp_group]) self.cli_commit() swanctl_conf_lines = [ - 'version = 2', - 'auth = psk', - 'proposals = aes128-sha1-modp1024', - 'esp_proposals = aes128-sha1-modp1024', - 'local_addrs = 192.0.2.10 # dhcp:no', - 'remote_addrs = 203.0.113.45', - 'mode = tunnel', - 'local_ts = 172.16.10.0/24,172.16.11.0/24', - 'remote_ts = 172.17.10.0/24,172.17.11.0/24', - 'mark_in = 9437194', # 0x900000 + (vti)10 - 'mark_out = 9437194', - 'updown = "/etc/ipsec.d/vti-up-down vti10 no"' + f'version = 2', + f'auth = psk', + f'proposals = aes128-sha1-modp1024', + f'esp_proposals = aes128-sha1-modp1024', + f'local_addrs = 192.0.2.10 # dhcp:no', + f'remote_addrs = {peer_ip}', + f'mode = tunnel', + f'local_ts = 172.16.10.0/24,172.16.11.0/24', + f'remote_ts = 172.17.10.0/24,172.17.11.0/24', + f'if_id_in = {vti.lstrip("vti")}', # will be 10 for vti10 + f'if_id_out = {vti.lstrip("vti")}', + f'updown = "/etc/ipsec.d/vti-up-down {vti} no"' ] swanctl_secrets_lines = [ - 'id-local = 192.0.2.10 # dhcp:no', - 'id-remote = 203.0.113.45', - 'secret = "MYSECRETKEY"' + f'id-local = 192.0.2.10 # dhcp:no', + f'id-remote = {peer_ip}', + f'secret = "{secret}"' ] tmp_swanctl_conf = read_file(swanctl_file) @@ -192,62 +198,60 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): self.assertTrue(process_named_running('charon')) def test_dmvpn(self): - self.cli_delete(base_path) - self.cli_delete(nhrp_path) - self.cli_delete(tunnel_path) + tunnel_if = 'tun100' + nhrp_secret = 'secret' # Tunnel - self.cli_set(tunnel_path + ["tun100", "address", "172.16.253.134/29"]) - self.cli_set(tunnel_path + ["tun100", "encapsulation", "gre"]) - self.cli_set(tunnel_path + ["tun100", "source-address", "192.0.2.1"]) - self.cli_set(tunnel_path + ["tun100", "multicast", "enable"]) - self.cli_set(tunnel_path + ["tun100", "parameters", "ip", "key", "1"]) + self.cli_set(tunnel_path + [tunnel_if, 'address', '172.16.253.134/29']) + self.cli_set(tunnel_path + [tunnel_if, 'encapsulation', 'gre']) + self.cli_set(tunnel_path + [tunnel_if, 'source-address', '192.0.2.1']) + self.cli_set(tunnel_path + [tunnel_if, 'multicast', 'enable']) + self.cli_set(tunnel_path + [tunnel_if, 'parameters', 'ip', 'key', '1']) # NHRP - self.cli_set(nhrp_path + ["tunnel", "tun100", "cisco-authentication", "secret"]) - self.cli_set(nhrp_path + ["tunnel", "tun100", "holding-time", "300"]) - self.cli_set(nhrp_path + ["tunnel", "tun100", "multicast", "dynamic"]) - self.cli_set(nhrp_path + ["tunnel", "tun100", "redirect"]) - self.cli_set(nhrp_path + ["tunnel", "tun100", "shortcut"]) + self.cli_set(nhrp_path + ['tunnel', tunnel_if, 'cisco-authentication', nhrp_secret]) + self.cli_set(nhrp_path + ['tunnel', tunnel_if, 'holding-time', '300']) + self.cli_set(nhrp_path + ['tunnel', tunnel_if, 'multicast', 'dynamic']) + self.cli_set(nhrp_path + ['tunnel', tunnel_if, 'redirect']) + self.cli_set(nhrp_path + ['tunnel', tunnel_if, 'shortcut']) # IKE/ESP Groups - self.cli_set(base_path + ["esp-group", "ESP-HUB", "compression", "disable"]) - self.cli_set(base_path + ["esp-group", "ESP-HUB", "lifetime", "1800"]) - self.cli_set(base_path + ["esp-group", "ESP-HUB", "mode", "transport"]) - self.cli_set(base_path + ["esp-group", "ESP-HUB", "pfs", "dh-group2"]) - self.cli_set(base_path + ["esp-group", "ESP-HUB", "proposal", "1", "encryption", "aes256"]) - self.cli_set(base_path + ["esp-group", "ESP-HUB", "proposal", "1", "hash", "sha1"]) - self.cli_set(base_path + ["esp-group", "ESP-HUB", "proposal", "2", "encryption", "3des"]) - self.cli_set(base_path + ["esp-group", "ESP-HUB", "proposal", "2", "hash", "md5"]) - self.cli_set(base_path + ["ike-group", "IKE-HUB", "ikev2-reauth", "no"]) - self.cli_set(base_path + ["ike-group", "IKE-HUB", "key-exchange", "ikev1"]) - self.cli_set(base_path + ["ike-group", "IKE-HUB", "lifetime", "3600"]) - self.cli_set(base_path + ["ike-group", "IKE-HUB", "proposal", "1", "dh-group", "2"]) - self.cli_set(base_path + ["ike-group", "IKE-HUB", "proposal", "1", "encryption", "aes256"]) - self.cli_set(base_path + ["ike-group", "IKE-HUB", "proposal", "1", "hash", "sha1"]) - self.cli_set(base_path + ["ike-group", "IKE-HUB", "proposal", "2", "dh-group", "2"]) - self.cli_set(base_path + ["ike-group", "IKE-HUB", "proposal", "2", "encryption", "aes128"]) - self.cli_set(base_path + ["ike-group", "IKE-HUB", "proposal", "2", "hash", "sha1"]) + self.cli_set(base_path + ['esp-group', esp_group, 'compression', 'disable']) + self.cli_set(base_path + ['esp-group', esp_group, 'lifetime', '1800']) + self.cli_set(base_path + ['esp-group', esp_group, 'mode', 'transport']) + self.cli_set(base_path + ['esp-group', esp_group, 'pfs', 'dh-group2']) + self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '1', 'encryption', 'aes256']) + self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '1', 'hash', 'sha1']) + self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '2', 'encryption', '3des']) + self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '2', 'hash', 'md5']) + self.cli_set(base_path + ['ike-group', ike_group, 'ikev2-reauth', 'no']) + self.cli_set(base_path + ['ike-group', ike_group, 'key-exchange', 'ikev1']) + self.cli_set(base_path + ['ike-group', ike_group, 'lifetime', '3600']) + self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'dh-group', '2']) + self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'encryption', 'aes256']) + self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '1', 'hash', 'sha1']) + self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '2', 'dh-group', '2']) + self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '2', 'encryption', 'aes128']) + self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '2', 'hash', 'sha1']) # Profile - self.cli_set(base_path + ["ipsec-interfaces", "interface", "eth0"]) - self.cli_set(base_path + ["profile", "NHRPVPN", "authentication", "mode", "pre-shared-secret"]) - self.cli_set(base_path + ["profile", "NHRPVPN", "authentication", "pre-shared-secret", "secret"]) - self.cli_set(base_path + ["profile", "NHRPVPN", "bind", "tunnel", "tun100"]) - self.cli_set(base_path + ["profile", "NHRPVPN", "esp-group", "ESP-HUB"]) - self.cli_set(base_path + ["profile", "NHRPVPN", "ike-group", "IKE-HUB"]) + self.cli_set(base_path + ['profile', 'NHRPVPN', 'authentication', 'mode', 'pre-shared-secret']) + self.cli_set(base_path + ['profile', 'NHRPVPN', 'authentication', 'pre-shared-secret', nhrp_secret]) + self.cli_set(base_path + ['profile', 'NHRPVPN', 'bind', 'tunnel', tunnel_if]) + self.cli_set(base_path + ['profile', 'NHRPVPN', 'esp-group', esp_group]) + self.cli_set(base_path + ['profile', 'NHRPVPN', 'ike-group', ike_group]) self.cli_commit() swanctl_lines = [ - 'proposals = aes256-sha1-modp1024,aes128-sha1-modp1024', - 'version = 1', - 'rekey_time = 3600s', - 'esp_proposals = aes256-sha1-modp1024,3des-md5-modp1024', - 'local_ts = dynamic[gre]', - 'remote_ts = dynamic[gre]', - 'mode = transport', - 'secret = secret' + f'proposals = aes256-sha1-modp1024,aes128-sha1-modp1024', + f'version = 1', + f'rekey_time = 3600s', + f'esp_proposals = aes256-sha1-modp1024,3des-md5-modp1024', + f'local_ts = dynamic[gre]', + f'remote_ts = dynamic[gre]', + f'mode = transport', + f'secret = {nhrp_secret}' ] tmp_swanctl_conf = read_file('/etc/swanctl/swanctl.conf') diff --git a/src/completion/list_dumpable_interfaces.py b/src/completion/list_dumpable_interfaces.py index 101c92fbe..67bf6206b 100755 --- a/src/completion/list_dumpable_interfaces.py +++ b/src/completion/list_dumpable_interfaces.py @@ -7,6 +7,6 @@ import re from vyos.util import cmd if __name__ == '__main__': - out = cmd('/usr/sbin/tcpdump -D').split('\n') + out = cmd('tcpdump -D').split('\n') intfs = " ".join(map(lambda s: re.search(r'\d+\.(\S+)\s', s).group(1), out)) print(intfs) diff --git a/src/conf_mode/interfaces-vti.py b/src/conf_mode/interfaces-vti.py index 6ff23ae59..1b38304c1 100755 --- a/src/conf_mode/interfaces-vti.py +++ b/src/conf_mode/interfaces-vti.py @@ -36,40 +36,9 @@ def get_config(config=None): conf = Config() base = ['interfaces', 'vti'] vti = get_interface_dict(conf, base) - - # VTI is more then an interface - we retrieve the "real" configuration from - # the IPsec peer configuration which binds this VTI - conf.set_level([]) - vti['ipsec'] = conf.get_config_dict(['vpn', 'ipsec', 'site-to-site', 'peer'], - key_mangling=('-', '_'), get_first_key=True, - no_tag_node_value_mangle=True) - - for peer, peer_config in vti['ipsec'].items(): - if dict_search('vti.bind', peer_config) == vti['ifname']: - vti['remote'] = peer - if 'local_address' in peer_config: - vti['source_address'] = peer_config['local_address'] - # we also need to "calculate" a per vti individual key - base = 0x900000 - vti['key'] = base + int(vti['ifname'].lstrip('vti')) - return vti def verify(vti): - if 'deleted' in vti: - return None - - ifname = vti['ifname'] - found = False - for peer, peer_config in vti['ipsec'].items(): - if dict_search('vti.bind', peer_config) == ifname: - found = True - # we can now stop processing the for loop - break - if not found: - tmp = vti['ifname'] - raise ConfigError(f'Interface "{ifname}" not referenced in any VPN configuration!') - return None def generate(vti): diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py index 74253c2d7..95f277d74 100755 --- a/src/conf_mode/protocols_bgp.py +++ b/src/conf_mode/protocols_bgp.py @@ -88,6 +88,10 @@ def verify_remote_as(peer_config, bgp_config): tmp = dict_search(f'peer_group.{peer_group_name}.remote_as', bgp_config) if tmp: return tmp + if 'v6only' in peer_config['interface']: + if 'remote_as' in peer_config['interface']['v6only']: + return peer_config['interface']['v6only']['remote_as'] + return None def verify(bgp): diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py index e8e8b453a..70b4c52e6 100755 --- a/src/conf_mode/vpn_ipsec.py +++ b/src/conf_mode/vpn_ipsec.py @@ -83,8 +83,6 @@ esp_ciphers = {} dhcp_wait_attempts = 2 dhcp_wait_sleep = 1 -mark_base = 0x900000 - swanctl_dir = '/etc/swanctl' ipsec_conf = '/etc/ipsec.conf' ipsec_secrets = '/etc/ipsec.secrets' @@ -358,8 +356,13 @@ def generate_pki_files(pki, x509_conf): f.write(wrap_private_key(key_data, protected)) def generate(ipsec): - data = {} + if not ipsec: + for config_file in [ipsec_conf, ipsec_secrets, interface_conf, swanctl_conf]: + if os.path.isfile(config_file): + os.unlink(config_file) + return + data = {} if ipsec: if ipsec['dhcp_no_address']: with open(DHCP_HOOK_IFLIST, 'w') as f: @@ -368,7 +371,6 @@ def generate(ipsec): data = ipsec data['authby'] = authby_translate data['ciphers'] = {'ike': ike_ciphers, 'esp': esp_ciphers} - data['marks'] = {} data['rsa_local_key'] = verify_rsa_local_key(ipsec) for path in [swanctl_dir, CERT_PATH, CA_PATH, CRL_PATH]: @@ -394,10 +396,6 @@ def generate(ipsec): data['site_to_site']['peer'][peer]['local_address'] = local_ip - if 'vti' in peer_conf and 'bind' in peer_conf['vti']: - vti_interface = peer_conf['vti']['bind'] - data['marks'][vti_interface] = get_mark(vti_interface) - if 'tunnel' in peer_conf: for tunnel, tunnel_conf in peer_conf['tunnel'].items(): local_prefixes = dict_search('local.prefix', tunnel_conf) @@ -469,10 +467,6 @@ def apply(ipsec): resync_l2tp(ipsec) resync_nhrp(ipsec) -def get_mark(vti_interface): - vti_num = int(vti_interface.lstrip('vti')) - return mark_base + vti_num - if __name__ == '__main__': try: ipsec = get_config() |