Page MenuHomeVyOS Platform

ipsec-settings.py
No OneTemporary

Size
9 KB
Referenced Files
None
Subscribers
None

ipsec-settings.py

#!/usr/bin/env python3
#
# Copyright (C) 2018-2020 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 re
import os
from time import sleep
from sys import exit
from vyos.config import Config
from vyos import ConfigError
from vyos.util import call
from vyos.template import render
ra_conn_name = "remote-access"
charon_conf_file = "/etc/strongswan.d/charon.conf"
ipsec_secrets_file = "/etc/ipsec.secrets"
ipsec_ra_conn_dir = "/etc/ipsec.d/tunnels/"
ipsec_ra_conn_file = ipsec_ra_conn_dir + ra_conn_name
ipsec_conf_file = "/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 ###"
charon_pidfile = "/var/run/charon.pid"
def get_config():
config = Config()
data = {"install_routes": "yes"}
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
def write_ipsec_secrets(c):
if c.get("ipsec_l2tp_auth_mode") == "pre-shared-secret":
secret_txt = "{0}\n{1} %any : PSK \"{2}\"\n{3}\n".format(delim_ipsec_l2tp_begin, c['outside_addr'], c['ipsec_l2tp_secret'], delim_ipsec_l2tp_end)
elif data.get("ipsec_l2tp_auth_mode") == "x509":
secret_txt = "{0}\n: RSA {1}\n{2}\n".format(delim_ipsec_l2tp_begin, c['server_key_file_copied'], delim_ipsec_l2tp_end)
old_umask = os.umask(0o077)
with open(ipsec_secrets_file, 'a+') as f:
f.write(secret_txt)
os.umask(old_umask)
def write_ipsec_conf(c):
ipsec_confg_txt = "{0}\ninclude {1}\n{2}\n".format(delim_ipsec_l2tp_begin, ipsec_ra_conn_file, delim_ipsec_l2tp_end)
old_umask = os.umask(0o077)
with open(ipsec_conf_file, 'a+') as f:
f.write(ipsec_confg_txt)
os.umask(old_umask)
### Remove config from file by delimiter
def remove_confs(delim_begin, delim_end, conf_file):
call("sed -i '/"+delim_begin+"/,/"+delim_end+"/d' "+conf_file)
### 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 = call('cp -f '+file_path+' '+dts_path)
if ret:
raise ConfigError("L2TP VPN configuration error: Cannot copy "+file_path)
def verify(data):
# 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):
render(charon_conf_file, 'ipsec/charon.tmpl', data, trim_blocks=True)
if data["ipsec_l2tp"]:
remove_confs(delim_ipsec_l2tp_begin, delim_ipsec_l2tp_end, ipsec_secrets_file)
# old_umask = os.umask(0o077)
# render(ipsec_secrets_file, 'ipsec/ipsec.secrets.tmpl', data, trim_blocks=True)
# os.umask(old_umask)
## Use this method while IPSec CLI handler won't be overwritten to python
write_ipsec_secrets(data)
old_umask = os.umask(0o077)
# Create tunnels directory if does not exist
if not os.path.exists(ipsec_ra_conn_dir):
os.makedirs(ipsec_ra_conn_dir)
render(ipsec_ra_conn_file, 'ipsec/remote-access.tmpl', data, trim_blocks=True)
os.umask(old_umask)
remove_confs(delim_ipsec_l2tp_begin, delim_ipsec_l2tp_end, ipsec_conf_file)
# old_umask = os.umask(0o077)
# render(ipsec_conf_file, 'ipsec/ipsec.conf.tmpl', data, trim_blocks=True)
# os.umask(old_umask)
## Use this method while IPSec CLI handler won't be overwritten to python
write_ipsec_conf(data)
else:
if os.path.exists(ipsec_ra_conn_file):
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_file)
remove_confs(delim_ipsec_l2tp_begin, delim_ipsec_l2tp_end, ipsec_conf_file)
def restart_ipsec():
call('ipsec restart >&/dev/null')
# counter for apply swanctl config
counter = 10
while counter <= 10:
if os.path.exists(charon_pidfile):
call('swanctl -q >&/dev/null')
break
counter -=1
sleep(1)
if counter == 0:
raise ConfigError('VPN configuration error: IPSec is not running.')
def apply(data):
# Restart IPSec daemon
restart_ipsec()
if __name__ == '__main__':
try:
c = get_config()
verify(c)
generate(c)
apply(c)
except ConfigError as e:
print(e)
exit(1)

File Metadata

Mime Type
text/x-script.python
Expires
Mon, Dec 15, 9:10 PM (3 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3073061
Default Alt Text
ipsec-settings.py (9 KB)

Event Timeline