Skip to content

Commit

Permalink
net/wireguard - make our service control a bit smarted in case of a […
Browse files Browse the repository at this point in the history
…re]configure. If the endresult from the interface perspective is guaranteed the same as we used the last time, just omit the stop() operation and reload the configuration. This should warrant a fluent reload when only peers are added. for opnsense#3358
  • Loading branch information
AdSchellevis committed Aug 31, 2023
1 parent 0bb9d63 commit 6b46942
Showing 1 changed file with 48 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ function wg_start($server, $fhandle)
// flush checksum to ease change detection
fseek($fhandle, 0);
ftruncate($fhandle, 0);
fwrite($fhandle, @md5_file($server->cnfFilename));
fwrite($fhandle, @md5_file($server->cnfFilename) . "|". wg_reconfigure_hash($server));
syslog(LOG_NOTICE, "Wireguard interface {$server->name} ({$server->interface}) started");
}

Expand All @@ -110,6 +110,43 @@ function wg_stop($server)
}


/**
* Calculate a hash which determines if we are able to reconfigure without a restart of the tunnel.
* We currently assume if something changed on the interface or peer routes are being pushed, it's safer to
* restart then reload.
*/
function wg_reconfigure_hash($server)
{
if (empty((string)$server->disableroutes)) {
return md5(uniqid('', true)); // random hash, should always reconfigure
}
return md5(
sprintf(
'%s|%s|%s',
$server->tunneladdress,
$server->mtu,
$server->gateway
)
);
}

/**
* The stat hash file answers two questions, [1] has anything changed, which is answered using an md5 hash of the
* configuration file. The second question, if something has changed, is it safe to only reload the configuration.
* This is answered by wg_reconfigure_hash() for the instance in question.
*/
function get_stat_hash($fhandle)
{
fseek($fhandle, 0);
$payload = stream_get_contents($fhandle) ?? '';
$parts = explode('|', $payload);
return [
'file' => $parts[0] ?? '',
'interface' => $parts[1] ?? ''
];

}

$opts = getopt('ah', [], $optind);
$args = array_slice($argv, $optind);

Expand Down Expand Up @@ -148,10 +185,18 @@ function wg_stop($server)
break;
case 'configure':
if (
@md5_file($node->cnfFilename) != @file_get_contents($node->statFilename) ||
@md5_file($node->cnfFilename) != get_stat_hash($statHandle)['file'] ||
!does_interface_exist((string)$node->interface)
) {
wg_stop($node);
if (get_stat_hash($statHandle)['interface'] != wg_reconfigure_hash($node)) {
// Fluent reloading not supported for this instance, make sure the user is informed
syslog(
LOG_NOTICE,
"Wireguard interface {$node->name} ({$node->interface}) ".
"can not reconfigure without stopping it first."
);
wg_stop($node);
}
wg_start($node, $statHandle);
}
break;
Expand Down

0 comments on commit 6b46942

Please sign in to comment.