summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2020-04-11 00:21:43 +0200
committerChristian Poessinger <christian@poessinger.com>2020-04-11 11:25:59 +0200
commit033062f56be9d531b1911e7d7516d7986aa68b46 (patch)
tree0df8289cf44e3822785c7a219a51dc94073f4088
parent02b4c640c8c02124ee8c1c1ee4da82c3367f20d0 (diff)
downloadvyos-1x-033062f56be9d531b1911e7d7516d7986aa68b46.tar.gz
vyos-1x-033062f56be9d531b1911e7d7516d7986aa68b46.zip
vpn: l2tp: T2264: migrate to new dictionary keys for radius auth
-rw-r--r--data/templates/l2tp/l2tp.config.tmpl78
-rwxr-xr-xsrc/conf_mode/vpn_l2tp.py276
2 files changed, 177 insertions, 177 deletions
diff --git a/data/templates/l2tp/l2tp.config.tmpl b/data/templates/l2tp/l2tp.config.tmpl
index cce526dd8..6ebbf1241 100644
--- a/data/templates/l2tp/l2tp.config.tmpl
+++ b/data/templates/l2tp/l2tp.config.tmpl
@@ -49,22 +49,22 @@ wins{{ loop.index }}={{ server }}
[l2tp]
verbose=1
ifname=l2tp%d
-ppp-max-mtu={{mtu}}
-mppe={{authentication['mppe']}}
+ppp-max-mtu={{ mtu }}
+mppe={{ ppp_mppe }}
{% if outside_addr %}
-bind={{outside_addr}}
+bind={{ outside_addr }}
{% endif %}
{% if lns_shared_secret %}
-secret={{lns_shared_secret}}
+secret={{ lns_shared_secret }}
{% endif %}
[client-ip-range]
0.0.0.0/0
-{% if (client_ip_pool) or (client_ip_subnets) %}
+{% if client_ip_pool or client_ip_subnets %}
[ip-pool]
{% if client_ip_pool %}
-{{client_ip_pool}}
+{{ client_ip_pool }}
{% endif -%}
{% if client_ip_subnets %}
{% for sn in client_ip_subnets %}
@@ -73,17 +73,34 @@ secret={{lns_shared_secret}}
{% endif %}
{% endif %}
{% if gateway_address %}
-gw-ip-address={{gateway_address}}
+gw-ip-address={{ gateway_address }}
{% endif %}
{% if auth_mode == 'local' %}
[chap-secrets]
-chap-secrets=/etc/accel-ppp/l2tp/chap-secrets
-{% if gateway_address %}
-gw-ip-address={{gateway_address}}
-{% endif %}
+chap-secrets={{ chap_secrets_file }}
+{% elif auth_mode == 'radius' %}
+[radius]
+verbose=1
+{% for r in radius_server %}
+server={{ r.server }},{{ r.key }},auth-port={{ r.port }},req-limit=0,fail-time={{ r.fail_time }}
+{% endfor -%}
{% endif %}
+acct-timeout={{ radius_acct_tmo }}
+timeout={{ radius_timeout }}
+max-try={{ radius_max_try }}
+
+{% if radius_nas_id %}
+nas-identifier={{ radius_nas_id }}
+{% endif -%}
+{% if radius_nas_ip %}
+nas-ip-address={{ radius_nas_ip }}
+{% endif -%}
+{% if radius_source_address %}
+bind={{ radius_source_address }}
+{% endif -%}
+
[ppp]
verbose=1
check-ip=1
@@ -108,36 +125,7 @@ ccp=0
ipv6=allow
{% endif %}
-{% if auth_mode == 'radius' %}
-[radius]
-{% for rsrv in authentication['radiussrv']: %}
-server={{rsrv}},{{authentication['radiussrv'][rsrv]['secret']}},\
-req-limit={{authentication['radiussrv'][rsrv]['req-limit']}},\
-fail-time={{authentication['radiussrv'][rsrv]['fail-time']}}
-{% endfor %}
-{% if authentication['radiusopt']['timeout'] %}
-timeout={{authentication['radiusopt']['timeout']}}
-{% endif %}
-{% if authentication['radiusopt']['acct-timeout'] %}
-acct-timeout={{authentication['radiusopt']['acct-timeout']}}
-{% endif %}
-{% if authentication['radiusopt']['max-try'] %}
-max-try={{authentication['radiusopt']['max-try']}}
-{% endif %}
-{% if authentication['radiusopt']['nas-id'] %}
-nas-identifier={{authentication['radiusopt']['nas-id']}}
-{% endif %}
-{% if authentication['radius_source_address'] %}
-nas-ip-address={{authentication['radius_source_address']}}
-{% endif -%}
-{% if authentication['radiusopt']['dae-srv'] %}
-dae-server={{authentication['radiusopt']['dae-srv']['ip-addr']}}:\
-{{authentication['radiusopt']['dae-srv']['port']}},\
-{{authentication['radiusopt']['dae-srv']['secret']}}
-{% endif -%}
-gw-ip-address={{gateway_address}}
-verbose=1
-{% endif -%}
+
{% if client_ipv6_pool %}
[ipv6-pool]
@@ -154,12 +142,12 @@ delegate={{prfx}}
verbose=1
{% endif %}
-{% if authentication['radiusopt']['shaper'] %}
+{% if radius_shaper_attr %}
[shaper]
verbose=1
-attr={{authentication['radiusopt']['shaper']['attr']}}
-{% if authentication['radiusopt']['shaper']['vendor'] %}
-vendor={{authentication['radiusopt']['shaper']['vendor']}}
+attr={{ radius_shaper_attr }}
+{% if radius_shaper_vendor %}
+vendor={{ radius_shaper_vendor }}
{% endif -%}
{% endif %}
diff --git a/src/conf_mode/vpn_l2tp.py b/src/conf_mode/vpn_l2tp.py
index b357be1ed..1058eeac6 100755
--- a/src/conf_mode/vpn_l2tp.py
+++ b/src/conf_mode/vpn_l2tp.py
@@ -19,6 +19,7 @@ import re
from copy import deepcopy
from socket import AF_INET, SOCK_STREAM, socket
+from stat import S_IRUSR, S_IWUSR, S_IRGRP
from sys import exit
from time import sleep
@@ -30,31 +31,36 @@ from vyos.util import run
from vyos.validate import is_ipv4
from vyos import ConfigError
-pidfile = r'/var/run/accel_l2tp.pid'
-l2tp_cnf_dir = r'/etc/accel-ppp/l2tp'
-chap_secrets = l2tp_cnf_dir + '/chap-secrets'
-l2tp_conf = l2tp_cnf_dir + '/l2tp.config'
-
+pidfile = '/var/run/accel_l2tp.pid'
+l2tp_conf = '/etc/accel-ppp/l2tp/l2tp.config'
+l2tp_chap_secrets = '/etc/accel-ppp/l2tp/chap-secrets'
default_config_data = {
- 'authentication': {
- 'radiussrv': {},
- 'radiusopt': {},
- 'mppe': 'prefer'
- },
- 'auth_proto' : [],
- 'local_users' : [],
- 'auth_mode' : 'local',
- 'radius_server' : [],
- 'outside_addr': '',
- 'gateway_address': '10.255.255.0',
- 'dnsv4': [],
- 'dnsv6': [],
- 'wins': [],
+ 'auth_mode': 'local',
+ 'auth_ppp_mppe': 'prefer',
+ 'auth_proto': ['auth_mschap_v2'],
+ 'chap_secrets_file': l2tp_chap_secrets,
'client_ip_pool': None,
'client_ip_subnets': [],
'client_ipv6_pool': {},
+ 'dnsv4': [],
+ 'dnsv6': [],
+ 'gateway_address': '10.255.255.0',
+ 'local_users' : [],
'mtu': '1436',
+ 'outside_addr': '',
+ 'ppp_mppe': 'prefer',
+ 'radius_server': [],
+ 'radius_acct_tmo': '3',
+ 'radius_max_try': '3',
+ 'radius_timeout': '3',
+ 'radius_nas_id': '',
+ 'radius_nas_ip': '',
+ 'radius_source_address': '',
+ 'radius_shaper_attr': '',
+ 'radius_shaper_vendor': '',
+ 'radius_dynamic_author': '',
+ 'wins': [],
'ip6_column': '',
'ip6_dp_column': '',
'ppp_options': {},
@@ -115,6 +121,20 @@ def get_config():
if conf.exists(['authentication', 'mode']):
l2tp['auth_mode'] = conf.return_value(['authentication', 'mode'])
+ if conf.exists(['authentication', 'protocols']):
+ auth_mods = {
+ 'pap': 'auth_pap',
+ 'chap': 'auth_chap_md5',
+ 'mschap': 'auth_mschap_v1',
+ 'mschap-v2': 'auth_mschap_v2'
+ }
+
+ for proto in conf.return_values(['authentication', 'protocols']):
+ l2tp['auth_proto'].append(auth_mods[proto])
+
+ if conf.exists(['authentication', 'mppe']):
+ l2tp['auth_ppp_mppe'] = conf.return_value(['authentication', 'mppe'])
+
#
# local auth
if conf.exists(['authentication', 'local-users']):
@@ -147,93 +167,98 @@ def get_config():
l2tp['local_users'].append(user)
- conf.set_level(base_path)
- # authentication mode radius servers and settings
- if conf.exists('authentication mode radius'):
- rsrvs = conf.list_nodes('authentication radius server')
- for rsrv in rsrvs:
- if conf.return_value('authentication radius server ' + rsrv + ' fail-time') == None:
- ftime = '0'
- else:
- ftime = str(conf.return_value(
- 'authentication radius server ' + rsrv + ' fail-time'))
- if conf.return_value('authentication radius-server ' + rsrv + ' req-limit') == None:
- reql = '0'
- else:
- reql = str(conf.return_value(
- 'authentication radius server ' + rsrv + ' req-limit'))
-
- l2tp['authentication']['radiussrv'].update(
- {
- rsrv: {
- 'secret': conf.return_value('authentication radius server ' + rsrv + ' key'),
- 'fail-time': ftime,
- 'req-limit': reql
- }
- }
- )
- # Source ip address feature
- if conf.exists('authentication radius source-address'):
- l2tp['authentication']['radius_source_address'] = conf.return_value(
- 'authentication radius source-address')
+ #
+ # RADIUS auth and settings
+ conf.set_level(base_path + ['authentication', 'radius'])
+ if conf.exists(['server']):
+ for server in conf.list_nodes(['server']):
+ radius = {
+ 'server' : server,
+ 'key' : '',
+ 'fail_time' : 0,
+ 'port' : '1812'
+ }
+
+ conf.set_level(base_path + ['authentication', 'radius', 'server', server])
+
+ if conf.exists(['fail-time']):
+ radius['fail-time'] = conf.return_value(['fail-time'])
+
+ if conf.exists(['port']):
+ radius['port'] = conf.return_value(['port'])
+
+ if conf.exists(['key']):
+ radius['key'] = conf.return_value(['key'])
+ if not conf.exists(['disable']):
+ l2tp['radius_server'].append(radius)
+
+ #
# advanced radius-setting
- if conf.exists('authentication radius acct-timeout'):
- l2tp['authentication']['radiusopt']['acct-timeout'] = conf.return_value(
- 'authentication radius acct-timeout')
- if conf.exists('authentication radius max-try'):
- l2tp['authentication']['radiusopt']['max-try'] = conf.return_value(
- 'authentication radius max-try')
- if conf.exists('authentication radius timeout'):
- l2tp['authentication']['radiusopt']['timeout'] = conf.return_value(
- 'authentication radius timeout')
- if conf.exists('authentication radius nas-identifier'):
- l2tp['authentication']['radiusopt']['nas-id'] = conf.return_value(
- 'authentication radius nas-identifier')
- if conf.exists('authentication radius dae-server'):
- # Set default dae-server port if not defined
- if conf.exists('authentication radius dae-server port'):
- dae_server_port = conf.return_value(
- 'authentication radius dae-server port')
- else:
- dae_server_port = "3799"
- l2tp['authentication']['radiusopt'].update(
- {
- 'dae-srv': {
- 'ip-addr': conf.return_value('authentication radius dae-server ip-address'),
- 'port': dae_server_port,
- 'secret': str(conf.return_value('authentication radius dae-server secret'))
- }
- }
- )
- # filter-id is the internal accel default if attribute is empty
- # set here as default for visibility which may change in the future
- if conf.exists('authentication radius rate-limit enable'):
- if not conf.exists('authentication radius rate-limit attribute'):
- l2tp['authentication']['radiusopt']['shaper'] = {
- 'attr': 'Filter-Id'
- }
- else:
- l2tp['authentication']['radiusopt']['shaper'] = {
- 'attr': conf.return_value('authentication radius rate-limit attribute')
- }
- if conf.exists('authentication radius rate-limit vendor'):
- l2tp['authentication']['radiusopt']['shaper']['vendor'] = conf.return_value(
- 'authentication radius rate-limit vendor')
-
- if conf.exists('client-ip-pool'):
- if conf.exists('client-ip-pool start') and conf.exists('client-ip-pool stop'):
- l2tp['client_ip_pool'] = conf.return_value(
- 'client-ip-pool start') + '-' + re.search('[0-9]+$', conf.return_value('client-ip-pool stop')).group(0)
-
- if conf.exists('client-ip-pool subnet'):
- l2tp['client_ip_subnets'] = conf.return_values(
- 'client-ip-pool subnet')
-
- if conf.exists('client-ipv6-pool prefix'):
+ conf.set_level(base_path + ['authentication', 'radius'])
+
+ if conf.exists(['acct-timeout']):
+ l2tp['radius_acct_tmo'] = conf.return_value(['acct-timeout'])
+
+ if conf.exists(['max-try']):
+ l2tp['radius_max_try'] = conf.return_value(['max-try'])
+
+ if conf.exists(['timeout']):
+ l2tp['radius_timeout'] = conf.return_value(['timeout'])
+
+ if conf.exists(['nas-identifier']):
+ l2tp['radius_nas_id'] = conf.return_value(['nas-identifier'])
+
+ if conf.exists(['nas-ip-address']):
+ l2tp['radius_nas_ip'] = conf.return_value(['nas-ip-address'])
+
+ if conf.exists(['source-address']):
+ l2tp['radius_source_address'] = conf.return_value(['source-address'])
+
+ # Dynamic Authorization Extensions (DOA)/Change Of Authentication (COA)
+ if conf.exists(['dynamic-author']):
+ dae = {
+ 'port' : '',
+ 'server' : '',
+ 'key' : ''
+ }
+
+ if conf.exists(['dynamic-author', 'server']):
+ dae['server'] = conf.return_value(['dynamic-author', 'server'])
+
+ if conf.exists(['dynamic-author', 'port']):
+ dae['port'] = conf.return_value(['dynamic-author', 'port'])
+
+ if conf.exists(['dynamic-author', 'key']):
+ dae['key'] = conf.return_value(['dynamic-author', 'key'])
+
+ l2tp['radius_dynamic_author'] = dae
+
+ if conf.exists(['rate-limit', 'enable']):
+ l2tp['radius_shaper_attr'] = 'Filter-Id'
+ c_attr = ['rate-limit', 'enable', 'attribute']
+ if conf.exists(c_attr):
+ l2tp['radius_shaper_attr'] = conf.return_value(c_attr)
+
+ c_vendor = ['rate-limit', 'enable', 'vendor']
+ if conf.exists(c_vendor):
+ l2tp['radius_shaper_vendor'] = conf.return_value(c_vendor)
+
+ conf.set_level(base_path)
+ if conf.exists(['client-ip-pool']):
+ if conf.exists(['client-ip-pool', 'start']) and conf.exists(['client-ip-pool', 'stop']):
+ start = conf.return_value(['client-ip-pool', 'start'])
+ stop = conf.return_value(['client-ip-pool', 'stop'])
+ l2tp['client_ip_pool'] = start + '-' + re.search('[0-9]+$', stop).group(0)
+
+ if conf.exists(['client-ip-pool', 'subnet']):
+ l2tp['client_ip_subnets'] = conf.return_values(['client-ip-pool', 'subnet'])
+
+ if conf.exists(['client-ipv6-pool', 'prefix']):
l2tp['client_ipv6_pool']['prefix'] = conf.return_values(
'client-ipv6-pool prefix')
l2tp['ip6_column'] = 'ip6,'
+
if conf.exists('client-ipv6-pool delegate-prefix'):
l2tp['client_ipv6_pool']['delegate_prefix'] = conf.return_values(
'client-ipv6-pool delegate-prefix')
@@ -257,26 +282,6 @@ def get_config():
'client-ip-pool subnet')[0])
l2tp['gateway_address'] = lst_ip[0]
- #
- # authentication protocols
- conf.set_level(base_path + ['authentication'])
- if conf.exists(['protocols']):
- auth_mods = {
- 'pap': 'auth_pap',
- 'chap': 'auth_chap_md5',
- 'mschap': 'auth_mschap_v1',
- 'mschap-v2': 'auth_mschap_v2'
- }
-
- for proto in conf.return_values(['protocols']):
- l2tp['auth_proto'].append(auth_mods[proto])
-
- else:
- l2tp['auth_proto'] = ['auth_mschap_v2']
-
- if conf.exists('authentication mppe'):
- l2tp['authentication']['mppe'] = conf.return_value(
- 'authentication mppe')
if conf.exists('idle'):
l2tp['idle_timeout'] = conf.return_value('idle')
@@ -319,13 +324,12 @@ def verify(l2tp):
raise ConfigError(f"Password required for user {user['name']}")
elif l2tp['auth_mode'] == 'radius':
- if len(l2tp['authentication']['radiussrv']) == 0:
- raise ConfigError('radius server required')
+ if len(l2tp['radius_server']) == 0:
+ raise ConfigError("RADIUS authentication requires at least one server")
- for rsrv in l2tp['authentication']['radiussrv']:
- if l2tp['authentication']['radiussrv'][rsrv]['secret'] == None:
- raise ConfigError('radius server ' + rsrv +
- ' needs a secret configured')
+ for radius in l2tp['radius_server']:
+ if not radius['key']:
+ raise ConfigError(f"Missing RADIUS secret for server {{ radius['key'] }}")
# check for the existence of a client ip pool
if not (l2tp['client_ip_pool'] or l2tp['client_ip_subnets']):
@@ -350,11 +354,13 @@ def verify(l2tp):
def generate(l2tp):
- if l2tp == None:
+ if not l2tp:
return None
- if not os.path.exists(l2tp_cnf_dir):
- os.makedirs(l2tp_cnf_dir)
+ # Create configuration directory if it's non existent
+ dirname = os.path.dirname(l2tp_conf)
+ if not os.path.isdir(dirname):
+ os.mkdir(dirname)
# Prepare Jinja2 template loader from files
tmpl_path = os.path.join(vyos_data_dir['data'], 'templates', 'l2tp')
@@ -369,14 +375,20 @@ def generate(l2tp):
if l2tp['auth_mode'] == 'local':
tmpl = env.get_template('chap-secrets.tmpl')
config_text = tmpl.render(l2tp)
- with open(chap_secrets, 'w') as f:
+ with open(l2tp['chap_secrets_file'], 'w') as f:
f.write(config_text)
+ os.chmod(l2tp['chap_secrets_file'], S_IRUSR | S_IWUSR | S_IRGRP)
+
+ else:
+ if os.path.exists(l2tp['chap_secrets_file']):
+ os.unlink(l2tp['chap_secrets_file'])
+
return None
def apply(l2tp):
- if l2tp == None:
+ if not l2tp:
if os.path.exists(pidfile):
_accel_cmd('shutdown hard')
if os.path.exists(pidfile):