summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsarthurdev <965089+sarthurdev@users.noreply.github.com>2021-06-14 13:04:04 +0200
committersarthurdev <965089+sarthurdev@users.noreply.github.com>2021-06-15 00:16:42 +0200
commit11b5636519b360074eb2877006f2d8d63d9f6610 (patch)
tree1ff04e1e0aba2167b746f2f1373544e3d38b055d /src
parent78099bccc510c90ad7cfa5f56475ba024d5d53a7 (diff)
downloadvyos-1x-11b5636519b360074eb2877006f2d8d63d9f6610.tar.gz
vyos-1x-11b5636519b360074eb2877006f2d8d63d9f6610.zip
ipsec: T2816: T645: T3613: Migrated IPsec to swanctl, includes multiple selectors, and selectors with VTI.
Diffstat (limited to 'src')
-rwxr-xr-xsrc/conf_mode/vpn_ipsec.py41
-rwxr-xr-xsrc/conf_mode/vpn_rsa-keys.py6
-rwxr-xr-xsrc/etc/dhcp/dhclient-exit-hooks.d/ipsec-dhclient-hook30
-rwxr-xr-xsrc/etc/ipsec.d/vti-up-down14
-rwxr-xr-xsrc/op_mode/vpn_ike_sa.py4
-rwxr-xr-xsrc/op_mode/vpn_ipsec.py13
6 files changed, 75 insertions, 33 deletions
diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py
index f80a9455a..433c51e7e 100755
--- a/src/conf_mode/vpn_ipsec.py
+++ b/src/conf_mode/vpn_ipsec.py
@@ -28,7 +28,6 @@ from vyos.template import render
from vyos.validate import is_ipv6_link_local
from vyos.util import call
from vyos.util import dict_search
-from vyos.util import get_interface_address
from vyos.util import process_named_running
from vyos.util import run
from vyos.util import cidr_fit
@@ -37,9 +36,9 @@ from vyos import airbag
airbag.enable()
authby_translate = {
- 'pre-shared-secret': 'secret',
- 'rsa': 'rsasig',
- 'x509': 'rsasig'
+ 'pre-shared-secret': 'psk',
+ 'rsa': 'pubkey',
+ 'x509': 'pubkey'
}
default_pfs = 'dh-group2'
pfs_translate = {
@@ -80,8 +79,10 @@ dhcp_wait_sleep = 1
mark_base = 0x900000
-CA_PATH = "/etc/ipsec.d/cacerts/"
-CRL_PATH = "/etc/ipsec.d/crls/"
+CERT_PATH="/etc/swanctl/x509/"
+KEY_PATH="/etc/swanctl/private/"
+CA_PATH = "/etc/swanctl/x509ca/"
+CRL_PATH = "/etc/swanctl/x509crl/"
DHCP_BASE = "/var/lib/dhcp/dhclient"
DHCP_HOOK_IFLIST="/tmp/ipsec_dhcp_waiting"
@@ -126,7 +127,7 @@ def get_config(config=None):
if enc and hash:
ciphers.append(f"{enc}-{hash}-{pfs_translate[pfs]}" if pfs else f"{enc}-{hash}")
- ike_ciphers[group] = ','.join(ciphers) + '!'
+ ike_ciphers[group] = ','.join(ciphers)
if 'esp_group' in ipsec:
for group, esp_conf in ipsec['esp_group'].items():
@@ -146,7 +147,7 @@ def get_config(config=None):
hash = proposal['hash'] if 'hash' in proposal else None
if enc and hash:
ciphers.append(f"{enc}-{hash}-{pfs_translate[pfs]}" if pfs else f"{enc}-{hash}")
- esp_ciphers[group] = ','.join(ciphers) + '!'
+ esp_ciphers[group] = ','.join(ciphers)
return ipsec
@@ -324,7 +325,6 @@ def generate(ipsec):
data['ciphers'] = {'ike': ike_ciphers, 'esp': esp_ciphers}
data['marks'] = {}
data['rsa_local_key'] = verify_rsa_local_key(ipsec)
- data['x509_path'] = X509_PATH
if 'site_to_site' in data and 'peer' in data['site_to_site']:
for peer, peer_conf in ipsec['site_to_site']['peer'].items():
@@ -332,6 +332,12 @@ def generate(ipsec):
continue
if peer_conf['authentication']['mode'] == 'x509':
+ cert_file = os.path.join(X509_PATH, peer_conf['authentication']['x509']['cert_file'])
+ call(f'cp -f {cert_file} {CERT_PATH}')
+
+ key_file = os.path.join(X509_PATH, peer_conf['authentication']['x509']['key']['file'])
+ call(f'cp -f {key_file} {KEY_PATH}')
+
ca_cert_file = os.path.join(X509_PATH, peer_conf['authentication']['x509']['ca_cert_file'])
call(f'cp -f {ca_cert_file} {CA_PATH}')
@@ -350,15 +356,22 @@ def generate(ipsec):
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)
- else:
+
+ if 'tunnel' in peer_conf:
for tunnel, tunnel_conf in peer_conf['tunnel'].items():
- local_prefix = dict_search('local.prefix', tunnel_conf)
- remote_prefix = dict_search('remote.prefix', tunnel_conf)
+ local_prefixes = dict_search('local.prefix', tunnel_conf)
+ remote_prefixes = dict_search('remote.prefix', tunnel_conf)
- if not local_prefix or not remote_prefix:
+ if not local_prefixes or not remote_prefixes:
continue
- passthrough = cidr_fit(local_prefix, remote_prefix)
+ passthrough = []
+
+ for local_prefix in local_prefixes:
+ for remote_prefix in remote_prefixes:
+ if cidr_fit(local_prefix, remote_prefix):
+ passthrough.append(local_prefix)
+
data['site_to_site']['peer'][peer]['tunnel'][tunnel]['passthrough'] = passthrough
if 'logging' in ipsec and 'log_modes' in ipsec['logging']:
diff --git a/src/conf_mode/vpn_rsa-keys.py b/src/conf_mode/vpn_rsa-keys.py
index 6cf7eba6e..c6ff369ad 100755
--- a/src/conf_mode/vpn_rsa-keys.py
+++ b/src/conf_mode/vpn_rsa-keys.py
@@ -29,7 +29,8 @@ from Crypto.PublicKey.RSA import construct
airbag.enable()
LOCAL_KEY_PATHS = ['/config/auth/', '/config/ipsec.d/rsa-keys/']
-LOCAL_OUTPUT = '/etc/ipsec.d/certs/localhost.pub'
+LOCAL_OUTPUT = '/etc/swanctl/pubkey/localhost.pub'
+LOCAL_KEY_OUTPUT = '/etc/swanctl/private/localhost.key'
def get_config(config=None):
if config:
@@ -68,6 +69,7 @@ def generate(conf):
if 'local_key' in conf and 'file' in conf['local_key']:
local_key = conf['local_key']['file']
local_key_path = get_local_key(local_key)
+ call(f'sudo cp -f {local_key_path} {LOCAL_KEY_OUTPUT}')
call(f'sudo /usr/bin/openssl rsa -in {local_key_path} -pubout -out {LOCAL_OUTPUT}')
if 'rsa_key_name' in conf:
@@ -82,7 +84,7 @@ def generate(conf):
else:
remote_key = bytes('-----BEGIN PUBLIC KEY-----\n' + remote_key + '\n-----END PUBLIC KEY-----\n', 'utf-8')
- with open(f'/etc/ipsec.d/certs/{key_name}.pub', 'wb') as f:
+ with open(f'/etc/swanctl/pubkey/{key_name}.pub', 'wb') as f:
f.write(remote_key)
def migrate_from_vyatta_key(data):
diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/ipsec-dhclient-hook b/src/etc/dhcp/dhclient-exit-hooks.d/ipsec-dhclient-hook
index e00e5fe6e..a7a9a2ce6 100755
--- a/src/etc/dhcp/dhclient-exit-hooks.d/ipsec-dhclient-hook
+++ b/src/etc/dhcp/dhclient-exit-hooks.d/ipsec-dhclient-hook
@@ -1,4 +1,18 @@
#!/bin/bash
+#
+# 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/>.
if [ "$reason" == "REBOOT" ] || [ "$reason" == "EXPIRE" ]; then
exit 0
@@ -24,8 +38,7 @@ import re
from vyos.util import call
from vyos.util import cmd
-IPSEC_CONF="/etc/ipsec.conf"
-IPSEC_SECRETS="/etc/ipsec.secrets"
+SWANCTL_CONF="/etc/swanctl/swanctl.conf"
def getlines(file):
with open(file, 'r') as f:
@@ -41,7 +54,7 @@ def ipsec_down(ip_address):
connection_name = None
for line in status.split("\n"):
if line.find(ip_address) > 0:
- regex_match = re.search(r'(peer-[^:\[]+)', line)
+ regex_match = re.search(r'(peer_[^:\[]+)', line)
if regex_match:
connection_name = regex_match[1]
break
@@ -53,8 +66,7 @@ if __name__ == '__main__':
new_ip = os.getenv('new_ip_address')
old_ip = os.getenv('old_ip_address')
- conf_lines = getlines(IPSEC_CONF)
- secrets_lines = getlines(IPSEC_SECRETS)
+ conf_lines = getlines(SWANCTL_CONF)
found = False
to_match = f'# dhcp:{interface}'
@@ -68,9 +80,9 @@ if __name__ == '__main__':
secrets_lines[i] = line.replace(old_ip, new_ip)
if found:
- writelines(IPSEC_CONF, conf_lines)
- writelines(IPSEC_SECRETS, secrets_lines)
+ writelines(SWANCTL_CONF, conf_lines)
ipsec_down(old_ip)
- call('sudo /usr/sbin/ipsec rereadall')
- call('sudo /usr/sbin/ipsec reload')
+ call('sudo ipsec rereadall')
+ call('sudo ipsec reload')
+ call('sudo swanctl -q')
PYEND \ No newline at end of file
diff --git a/src/etc/ipsec.d/vti-up-down b/src/etc/ipsec.d/vti-up-down
index 0e1cd7753..2b66dd9e6 100755
--- a/src/etc/ipsec.d/vti-up-down
+++ b/src/etc/ipsec.d/vti-up-down
@@ -1,4 +1,18 @@
#!/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/>.
## Script called up strongswan to bring the vti interface up/down based on the state of the IPSec tunnel.
## Called as vti_up_down vti_intf_name
diff --git a/src/op_mode/vpn_ike_sa.py b/src/op_mode/vpn_ike_sa.py
index 28da9f8dc..fe016da45 100755
--- a/src/op_mode/vpn_ike_sa.py
+++ b/src/op_mode/vpn_ike_sa.py
@@ -36,9 +36,9 @@ def ike_sa(peer, nat):
peers = []
for conn in sas:
for name, sa in conn.items():
- if peer and not name.startswith('peer-' + peer):
+ if peer and not name.startswith('peer_' + peer):
continue
- if name.startswith('peer-') and name in peers:
+ if name.startswith('peer_') and name in peers:
continue
if nat and 'nat-local' not in sa:
continue
diff --git a/src/op_mode/vpn_ipsec.py b/src/op_mode/vpn_ipsec.py
index 434186abb..582b5ef95 100755
--- a/src/op_mode/vpn_ipsec.py
+++ b/src/op_mode/vpn_ipsec.py
@@ -100,13 +100,13 @@ def generate_x509_pair(name):
print(f'Private key: {X509_PATH}{name}.key')
def get_peer_connections(peer, tunnel, return_all = False):
- search = rf'^conn (peer-{peer}-(tunnel-[\d]+|vti))$'
+ search = rf'^[\s]*(peer_{peer}_(tunnel_[\d]+|vti)).*'
matches = []
- with open(IPSEC_CONF, 'r') as f:
+ with open(SWANCTL_CONF, 'r') as f:
for line in f.readlines():
result = re.match(search, line)
if result:
- suffix = f'tunnel-{tunnel}' if tunnel.isnumeric() else tunnel
+ suffix = f'tunnel_{tunnel}' if tunnel.isnumeric() else tunnel
if return_all or (result[2] == suffix):
matches.append(result[1])
return matches
@@ -171,13 +171,14 @@ def debug_peer(peer, tunnel):
if not tunnel or tunnel == 'all':
tunnel = ''
- conn = get_peer_connection(peer, tunnel)
+ conn = get_peer_connections(peer, tunnel)
- if not conn:
+ if not conns:
print('Peer not found, aborting')
return
- call(f'sudo /usr/sbin/ipsec statusall | grep {conn}')
+ for conn in conns:
+ call(f'sudo /usr/sbin/ipsec statusall | grep {conn}')
if __name__ == '__main__':
parser = argparse.ArgumentParser()