Page Menu
Home
VyOS Platform
Search
Configure Global Search
Log In
Files
F38742543
ipsec-settings.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
ipsec-settings.py
View Options
#!/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
(
0
o077
)
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}
\n
include {1}
\n
{2}
\n
"
.
format
(
delim_ipsec_l2tp_begin
,
ipsec_ra_conn_file
,
delim_ipsec_l2tp_end
)
old_umask
=
os
.
umask
(
0
o077
)
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
(
0
o077
)
# 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
Details
Attached
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)
Attached To
Mode
rVYOSONEX vyos-1x
Attached
Detach File
Event Timeline
Log In to Comment