diff --git a/src/etc/inc/plugins.inc.d/ipsec.inc b/src/etc/inc/plugins.inc.d/ipsec.inc
index a6f409d2e..b70196b1e 100644
--- a/src/etc/inc/plugins.inc.d/ipsec.inc
+++ b/src/etc/inc/plugins.inc.d/ipsec.inc
@@ -1731,26 +1731,7 @@ function ipsec_configure_vti($verbose = false, $device = null)
continue;
}
- $local_configured = null;
- $remote_configured = null;
- if (!empty($configured_intf[$intf])) {
- if (!is_ipaddr($configured_intf[$intf]['local'])) {
- $local_configured = ipsec_resolve($configured_intf[$intf]['local']);
- } else {
- $local_configured = $configured_intf[$intf]['local'];
- }
- if (!is_ipaddr($configured_intf[$intf]['remote'])) {
- $remote_configured = ipsec_resolve($configured_intf[$intf]['remote']);
- } else {
- $remote_configured = $configured_intf[$intf]['remote'];
- }
- }
- if (
- empty($configured_intf[$intf])
- || empty($intf_details['tunnel'])
- || $local_configured != $intf_details['tunnel']['src_addr']
- || $remote_configured != $intf_details['tunnel']['dest_addr']
- ) {
+ if (empty($configured_intf[$intf])) {
log_msg(sprintf("destroy interface %s", $intf), LOG_DEBUG);
legacy_interface_destroy($intf);
unset($current_interfaces[$intf]);
@@ -1797,7 +1778,10 @@ function ipsec_configure_vti($verbose = false, $device = null)
if (legacy_interface_create('ipsec', $intf) === null) {
break;
}
- mwexecf('/sbin/ifconfig %s reqid %s', [$intf, $intf_details['reqid']]);
+ }
+ // [re]initialise if_ipsec
+ mwexecf('/sbin/ifconfig %s reqid %s', [$intf, $intf_details['reqid']]);
+ if (!empty($intf_details['local']) && !empty($intf_details['remote'])) {
mwexecf('/sbin/ifconfig %s %s tunnel %s %s up', [
$intf,
is_ipaddrv6($intf_details['local']) ? 'inet6' : 'inet',
diff --git a/src/opnsense/mvc/app/models/OPNsense/IPsec/Swanctl.php b/src/opnsense/mvc/app/models/OPNsense/IPsec/Swanctl.php
index 0a85ada64..12f437a0c 100644
--- a/src/opnsense/mvc/app/models/OPNsense/IPsec/Swanctl.php
+++ b/src/opnsense/mvc/app/models/OPNsense/IPsec/Swanctl.php
@@ -92,6 +92,18 @@ class Swanctl extends BaseModel
}
}
+ if (
+ (empty((string)$node->local) && !empty((string)$node->remote)) ||
+ (!empty((string)$node->local) && empty((string)$node->remote))
+ ) {
+ $messages->appendMessage(
+ new Message(
+ gettext("A local and remote address should be provided or both should be left empty"),
+ $key . ".local"
+ )
+ );
+ }
+
if ($vti_inets['local'] != $vti_inets['remote']) {
$messages->appendMessage(new Message(gettext("Protocol families should match"), $key . ".local"));
}
diff --git a/src/opnsense/mvc/app/models/OPNsense/IPsec/Swanctl.xml b/src/opnsense/mvc/app/models/OPNsense/IPsec/Swanctl.xml
index 9bfad40d5..4b0193d18 100644
--- a/src/opnsense/mvc/app/models/OPNsense/IPsec/Swanctl.xml
+++ b/src/opnsense/mvc/app/models/OPNsense/IPsec/Swanctl.xml
@@ -365,13 +365,11 @@
N
N
- Y
Please specify a valid address.
N
N
- Y
Please specify a valid address.
diff --git a/src/opnsense/scripts/ipsec/updown_event.py b/src/opnsense/scripts/ipsec/updown_event.py
index 32cbe4021..dd3030460 100755
--- a/src/opnsense/scripts/ipsec/updown_event.py
+++ b/src/opnsense/scripts/ipsec/updown_event.py
@@ -29,7 +29,6 @@
handle swanctl.conf updown event
"""
import os
-import json
import subprocess
import argparse
import tempfile
@@ -37,7 +36,7 @@ import syslog
from configparser import ConfigParser
from lib import list_spds
-spd_filename = '/usr/local/etc/swanctl/reqid_events.conf'
+events_filename = '/usr/local/etc/swanctl/reqid_events.conf'
spd_add_cmd = 'spdadd -%(ipproto)s %(source)s %(destination)s any ' \
'-P out ipsec %(protocol)s/tunnel/%(local)s-%(remote)s/unique:%(reqid)s;'
@@ -54,47 +53,64 @@ if __name__ == '__main__':
if cmd_args.action and cmd_args.action.startswith('up'):
syslog.openlog('charon', facility=syslog.LOG_LOCAL4)
syslog.syslog(syslog.LOG_NOTICE, '[UPDOWN] received %s event for reqid %s' % (cmd_args.action, cmd_args.reqid))
- if os.path.exists(spd_filename):
+ if os.path.exists(events_filename):
cnf = ConfigParser()
- cnf.read(spd_filename)
+ cnf.read(events_filename)
spds = []
+ vtis = []
for section in cnf.sections():
if cnf.get(section, 'reqid') == cmd_args.reqid \
or cnf.get(section, 'connection_child') == cmd_args.connection_child:
- spds.append({
- 'reqid': cmd_args.reqid,
- 'local' : cmd_args.local,
- 'remote' : cmd_args.remote,
- 'destination': os.environ.get('PLUTO_PEER_CLIENT')
- })
- for opt in cnf.options(section):
- if cnf.get(section, opt).strip() != '':
- spds[-1][opt] = cnf.get(section, opt).strip()
+ if section.startswith('spd_'):
+ spds.append({
+ 'reqid': cmd_args.reqid,
+ 'local' : cmd_args.local,
+ 'remote' : cmd_args.remote,
+ 'destination': os.environ.get('PLUTO_PEER_CLIENT')
+ })
+ for opt in cnf.options(section):
+ if cnf.get(section, opt).strip() != '':
+ spds[-1][opt] = cnf.get(section, opt).strip()
+ elif section.startswith('vti_'):
+ vtis.append({
+ 'reqid': cmd_args.reqid,
+ 'local' : cmd_args.local,
+ 'remote' : cmd_args.remote
+ })
- # (re)apply manual policies if specified
- cur_spds = list_spds(automatic=False)
- set_key = []
- for spd in cur_spds:
- policy_found = False
- for mspd in spds:
- if mspd['source'] == spd['src'] and mspd['destination'] == spd['dst']:
- policy_found = True
- if policy_found or spd['reqid'] == cmd_args.reqid:
- set_key.append('spddelete -n %(src)s %(dst)s any -P %(direction)s;' % spd)
+ for vti in vtis:
+ if None in vti.values():
+ # incomplete, skip
+ continue
+ intf = 'ipsec%s' % vti['reqid']
+ proto = 'inet6' if vti['local'].find(':') > -1 else 'inet'
+ subprocess.run(['/sbin/ifconfig', intf, 'reqid', vti['reqid']])
+ subprocess.run(['/sbin/ifconfig', intf, proto, 'tunnel', vti['local'], vti['remote']])
- for spd in spds:
- if None in spd.values():
- # incomplete, skip
- continue
- spd['ipproto'] = '4' if spd.get('source', '').find(':') == -1 else '6'
- syslog.syslog(
- syslog.LOG_NOTICE,
- '[UPDOWN] add manual policy : %s' % (spd_add_cmd % spd)[7:]
- )
- set_key.append(spd_add_cmd % spd)
- if len(set_key) > 0:
- f = tempfile.NamedTemporaryFile(mode='wt', delete=False)
- f.write('\n'.join(set_key))
- f.close()
- subprocess.run(['/sbin/setkey', '-f', f.name], capture_output=True, text=True)
- os.unlink(f.name)
+ # (re)apply manual policies if specified
+ cur_spds = list_spds(automatic=False)
+ set_key = []
+ for spd in cur_spds:
+ policy_found = False
+ for mspd in spds:
+ if mspd['source'] == spd['src'] and mspd['destination'] == spd['dst']:
+ policy_found = True
+ if policy_found or spd['reqid'] == cmd_args.reqid:
+ set_key.append('spddelete -n %(src)s %(dst)s any -P %(direction)s;' % spd)
+
+ for spd in spds:
+ if None in spd.values():
+ # incomplete, skip
+ continue
+ spd['ipproto'] = '4' if spd.get('source', '').find(':') == -1 else '6'
+ syslog.syslog(
+ syslog.LOG_NOTICE,
+ '[UPDOWN] add manual policy : %s' % (spd_add_cmd % spd)[7:]
+ )
+ set_key.append(spd_add_cmd % spd)
+ if len(set_key) > 0:
+ f = tempfile.NamedTemporaryFile(mode='wt', delete=False)
+ f.write('\n'.join(set_key))
+ f.close()
+ subprocess.run(['/sbin/setkey', '-f', f.name], capture_output=True, text=True)
+ os.unlink(f.name)
diff --git a/src/opnsense/service/templates/OPNsense/IPsec/reqid_events.conf b/src/opnsense/service/templates/OPNsense/IPsec/reqid_events.conf
index 9c3055f60..f652c6b1a 100644
--- a/src/opnsense/service/templates/OPNsense/IPsec/reqid_events.conf
+++ b/src/opnsense/service/templates/OPNsense/IPsec/reqid_events.conf
@@ -16,3 +16,14 @@ description = {{spd.description}}
uuid = {{spd['@uuid']}}
{% endif %}
{% endfor %}
+
+{% for vti in helpers.toList('OPNsense.Swanctl.VTIs.VTI') %}
+{% if vti.enabled == '1' and vti.local|default('') == '' and vti.remote|default('') == '' %}
+
+[vti_{{vti['@uuid']|replace('-', '')}}]
+reqid = {{vti.reqid}}
+description = {{vti.description}}
+uuid = {{vti['@uuid']}}
+{% endif %}
+{% endfor %}
+