summaryrefslogtreecommitdiff
path: root/src/conf_mode/ipsec-settings.py
diff options
context:
space:
mode:
authorhagbard <vyosdev@derith.de>2019-07-25 09:48:08 -0700
committerhagbard <vyosdev@derith.de>2019-07-25 09:48:08 -0700
commitab5ca2796c1aad0043cc0db80299e4e2d42c1b22 (patch)
treebd0bcd4232e3099c38a142c0953f3c5a89b20d4d /src/conf_mode/ipsec-settings.py
parent36f8a1e4e5966c43c5330ff223fa2ef07d346b6e (diff)
downloadvyos-1x-ab5ca2796c1aad0043cc0db80299e4e2d42c1b22.tar.gz
vyos-1x-ab5ca2796c1aad0043cc0db80299e4e2d42c1b22.zip
[accel-l2tp] - T834: l2tp implementation
- node.def deletion for show remote-access - IPSec interface checking for L2TP - IPSec x509 for l2tp - verification of outside-address to warning since it was optional in the previous config
Diffstat (limited to 'src/conf_mode/ipsec-settings.py')
-rwxr-xr-xsrc/conf_mode/ipsec-settings.py197
1 files changed, 195 insertions, 2 deletions
diff --git a/src/conf_mode/ipsec-settings.py b/src/conf_mode/ipsec-settings.py
index 921f20491..8d25e7abd 100755
--- a/src/conf_mode/ipsec-settings.py
+++ b/src/conf_mode/ipsec-settings.py
@@ -16,16 +16,75 @@
#
#
+import sys
+import re
import os
import jinja2
+import syslog as sl
import vyos.config
import vyos.defaults
from vyos import ConfigError
+
+ra_conn_name = "remote-access"
charon_conf_file = "/etc/strongswan.d/charon.conf"
+ipsec_secrets_flie = "/etc/ipsec.secrets"
+ipsec_ra_conn_file = "/etc/ipsec.d/tunnels/"+ra_conn_name
+ipsec_conf_flie = "/etc/ipsec.conf"
+ca_cert_path = '/etc/ipsec.d/cacerts'
+server_cert_path = '/etc/ipsec.d/certs'
+server_key_path = '/etc/ipsec.d/private'
+delim_ipsec_l2tp_begin = "### VyOS L2TP VPN Begin ###"
+delim_ipsec_l2tp_end = "### VyOS L2TP VPN End ###"
+
+l2pt_ipsec_conf = '''
+{{delim_ipsec_l2tp_begin}}
+include {{ipsec_ra_conn_file}}
+{{delim_ipsec_l2tp_end}}
+'''
+
+l2pt_ipsec_secrets_conf = '''
+{{delim_ipsec_l2tp_begin}}
+{% if ipsec_l2tp_auth_mode == 'pre-shared-secret' %}
+{{outside_addr}} %any : PSK "{{ipsec_l2tp_secret}}"
+{% elif ipsec_l2tp_auth_mode == 'x509' %}
+: RSA {{server_key_file_copied}}
+{% endif%}
+{{delim_ipsec_l2tp_end}}
+'''
+l2tp_ipsec_ra_conn_conf = '''
+{{delim_ipsec_l2tp_begin}}
+conn {{ra_conn_name}}
+ type=transport
+ left={{outside_addr}}
+ leftsubnet=%dynamic[/1701]
+ rightsubnet=%dynamic
+ mark=%unique
+ auto=add
+ ike=aes256-sha1-modp1024,3des-sha1-modp1024,3des-sha1-modp1024!
+ dpddelay=15
+ dpdtimeout=45
+ dpdaction=clear
+ esp=aes256-sha1,3des-sha1!
+ rekey=no
+{% if ipsec_l2tp_auth_mode == 'pre-shared-secret' %}
+ authby=secret
+ leftauth=psk
+ rightauth=psk
+{% elif ipsec_l2tp_auth_mode == 'x509' %}
+ authby=rsasig
+ leftrsasigkey=%cert
+ rightrsasigkey=%cert
+ rightca=%same
+ leftcert={{server_cert_file_copied}}
+{% endif %}
+ ikelifetime={{ipsec_l2tp_ike_lifetime}}
+ keylife={{ipsec_l2tp_lifetime}}
+{{delim_ipsec_l2tp_end}}
+'''
def get_config():
config = vyos.config.Config()
@@ -34,10 +93,133 @@ def get_config():
if config.exists("vpn ipsec options disable-route-autoinstall"):
data["install_routes"] = "no"
+ if config.exists("vpn ipsec ipsec-interfaces interface"):
+ data["ipsec_interfaces"] = config.return_values("vpn ipsec ipsec-interfaces interface")
+
+ # Init config variables
+ data["delim_ipsec_l2tp_begin"] = delim_ipsec_l2tp_begin
+ data["delim_ipsec_l2tp_end"] = delim_ipsec_l2tp_end
+ data["ipsec_ra_conn_file"] = ipsec_ra_conn_file
+ data["ra_conn_name"] = ra_conn_name
+ # Get l2tp ipsec settings
+ data["ipsec_l2tp"] = False
+ conf_ipsec_command = "vpn l2tp remote-access ipsec-settings " #last space is useful
+ if config.exists(conf_ipsec_command):
+ data["ipsec_l2tp"] = True
+
+ # Authentication params
+ if config.exists(conf_ipsec_command + "authentication mode"):
+ data["ipsec_l2tp_auth_mode"] = config.return_value(conf_ipsec_command + "authentication mode")
+ if config.exists(conf_ipsec_command + "authentication pre-shared-secret"):
+ data["ipsec_l2tp_secret"] = config.return_value(conf_ipsec_command + "authentication pre-shared-secret")
+
+ # mode x509
+ if config.exists(conf_ipsec_command + "authentication x509 ca-cert-file"):
+ data["ipsec_l2tp_x509_ca_cert_file"] = config.return_value(conf_ipsec_command + "authentication x509 ca-cert-file")
+ if config.exists(conf_ipsec_command + "authentication x509 crl-file"):
+ data["ipsec_l2tp_x509_crl_file"] = config.return_value(conf_ipsec_command + "authentication x509 crl-file")
+ if config.exists(conf_ipsec_command + "authentication x509 server-cert-file"):
+ data["ipsec_l2tp_x509_server_cert_file"] = config.return_value(conf_ipsec_command + "authentication x509 server-cert-file")
+ data["server_cert_file_copied"] = server_cert_path+"/"+re.search('\w+(?:\.\w+)*$', config.return_value(conf_ipsec_command + "authentication x509 server-cert-file")).group(0)
+ if config.exists(conf_ipsec_command + "authentication x509 server-key-file"):
+ data["ipsec_l2tp_x509_server_key_file"] = config.return_value(conf_ipsec_command + "authentication x509 server-key-file")
+ data["server_key_file_copied"] = server_key_path+"/"+re.search('\w+(?:\.\w+)*$', config.return_value(conf_ipsec_command + "authentication x509 server-key-file")).group(0)
+ if config.exists(conf_ipsec_command + "authentication x509 server-key-password"):
+ data["ipsec_l2tp_x509_server_key_password"] = config.return_value(conf_ipsec_command + "authentication x509 server-key-password")
+
+ # Common l2tp ipsec params
+ if config.exists(conf_ipsec_command + "ike-lifetime"):
+ data["ipsec_l2tp_ike_lifetime"] = config.return_value(conf_ipsec_command + "ike-lifetime")
+ else:
+ data["ipsec_l2tp_ike_lifetime"] = "3600"
+
+ if config.exists(conf_ipsec_command + "lifetime"):
+ data["ipsec_l2tp_lifetime"] = config.return_value(conf_ipsec_command + "lifetime")
+ else:
+ data["ipsec_l2tp_lifetime"] = "3600"
+
+ if config.exists("vpn l2tp remote-access outside-address"):
+ data['outside_addr'] = config.return_value('vpn l2tp remote-access outside-address')
+
return data
+### ipsec secret l2tp
+def write_ipsec_secrets(c):
+ tmpl = jinja2.Template(l2pt_ipsec_secrets_conf, trim_blocks=True)
+ l2pt_ipsec_secrets_txt = tmpl.render(c)
+ old_umask = os.umask(0o077)
+ open(ipsec_secrets_flie,'w').write(l2pt_ipsec_secrets_txt)
+ os.umask(old_umask)
+ sl.syslog(sl.LOG_NOTICE, ipsec_secrets_flie + ' written')
+
+### ipsec remote access connection config
+def write_ipsec_ra_conn(c):
+ tmpl = jinja2.Template(l2tp_ipsec_ra_conn_conf, trim_blocks=True)
+ ipsec_ra_conn_txt = tmpl.render(c)
+ old_umask = os.umask(0o077)
+ open(ipsec_ra_conn_file,'w').write(ipsec_ra_conn_txt)
+ os.umask(old_umask)
+ sl.syslog(sl.LOG_NOTICE, ipsec_ra_conn_file + ' written')
+
+### Remove config from file by delimiter
+def remove_confs(delim_begin, delim_end, conf_file):
+ os.system("sed -i '/"+delim_begin+"/,/"+delim_end+"/d' "+conf_file)
+
+
+### Append "include /path/to/ra_conn" to ipsec conf file
+def append_ipsec_conf(c):
+ tmpl = jinja2.Template(l2pt_ipsec_conf, trim_blocks=True)
+ l2pt_ipsec_conf_txt = tmpl.render(c)
+ old_umask = os.umask(0o077)
+ open(ipsec_conf_flie,'a').write(l2pt_ipsec_conf_txt)
+ os.umask(old_umask)
+ sl.syslog(sl.LOG_NOTICE, ipsec_conf_flie + ' written')
+
+### Checking certificate storage and notice if certificate not in /config directory
+def check_cert_file_store(cert_name, file_path, dts_path):
+ if not re.search('^\/config\/.+', file_path):
+ print("Warning: \"" + file_path + "\" lies outside of /config/auth directory. It will not get preserved during image upgrade.")
+ #Checking file existence
+ if not os.path.isfile(file_path):
+ raise ConfigError("L2TP VPN configuration error: Invalid "+cert_name+" \""+file_path+"\"")
+ else:
+ ### Cpy file to /etc/ipsec.d/certs/ /etc/ipsec.d/cacerts/
+ # todo make check
+ ret = os.system('cp -f '+file_path+' '+dts_path)
+ if ret:
+ raise ConfigError("L2TP VPN configuration error: Cannot copy "+file_path)
+ else:
+ sl.syslog(sl.LOG_NOTICE, file_path + ' copied to '+dts_path)
+
def verify(data):
- pass
+ # l2tp ipsec check
+ if data["ipsec_l2tp"]:
+ # Checking dependecies for "authentication mode pre-shared-secret"
+ if data.get("ipsec_l2tp_auth_mode") == "pre-shared-secret":
+ if not data.get("ipsec_l2tp_secret"):
+ raise ConfigError("pre-shared-secret required")
+ if not data.get("outside_addr"):
+ raise ConfigError("outside-address not defined")
+
+ # Checking dependecies for "authentication mode x509"
+ if data.get("ipsec_l2tp_auth_mode") == "x509":
+ if not data.get("ipsec_l2tp_x509_server_key_file"):
+ raise ConfigError("L2TP VPN configuration error: \"server-key-file\" not defined.")
+ else:
+ check_cert_file_store("server-key-file", data['ipsec_l2tp_x509_server_key_file'], server_key_path)
+
+ if not data.get("ipsec_l2tp_x509_server_cert_file"):
+ raise ConfigError("L2TP VPN configuration error: \"server-cert-file\" not defined.")
+ else:
+ check_cert_file_store("server-cert-file", data['ipsec_l2tp_x509_server_cert_file'], server_cert_path)
+
+ if not data.get("ipsec_l2tp_x509_ca_cert_file"):
+ raise ConfigError("L2TP VPN configuration error: \"ca-cert-file\" must be defined for X.509")
+ else:
+ check_cert_file_store("ca-cert-file", data['ipsec_l2tp_x509_ca_cert_file'], ca_cert_path)
+
+ if not data.get('ipsec_interfaces'):
+ raise ConfigError("L2TP VPN configuration error: \"vpn ipsec ipsec-interfaces\" must be specified.")
def generate(data):
tmpl_path = os.path.join(vyos.defaults.directories["data"], "templates", "ipsec")
@@ -51,10 +233,21 @@ def generate(data):
with open(charon_conf_file, 'w') as f:
f.write(charon_conf)
+ if data["ipsec_l2tp"]:
+ remove_confs(delim_ipsec_l2tp_begin, delim_ipsec_l2tp_end, ipsec_conf_flie)
+ write_ipsec_secrets(data)
+ write_ipsec_ra_conn(data)
+ append_ipsec_conf(data)
+ else:
+ remove_confs(delim_ipsec_l2tp_begin, delim_ipsec_l2tp_end, ipsec_ra_conn_file)
+ remove_confs(delim_ipsec_l2tp_begin, delim_ipsec_l2tp_end, ipsec_secrets_flie)
+ remove_confs(delim_ipsec_l2tp_begin, delim_ipsec_l2tp_end, ipsec_conf_flie)
+
def apply(data):
# Do nothing
# StrongSWAN should only be restarted when actual tunnels are configured
- pass
+ # Restart ipsec for l2tp
+ os.system("ipsec restart >&/dev/null")
if __name__ == '__main__':
try: