Skip to content

Commit 105381b

Browse files
authored
feat: add reauthentication (#36)
1 parent 3c23522 commit 105381b

File tree

6 files changed

+53
-4
lines changed

6 files changed

+53
-4
lines changed

src/usr/local/emhttp/plugins/tailscale/include/Pages/Info.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
echo Utils::printRow($tr->tr("info.key_expire"), $tailscaleStatusInfo->KeyExpiration);
3333
echo Utils::printRow($tr->tr("info.tags"), $tailscaleStatusInfo->Tags);
3434
echo Utils::printRow("{$lockTranslate}: " . $tr->tr("enabled"), $tailscaleStatusInfo->LockEnabled);
35+
echo Utils::printRow($tr->tr("info.connected_via"), $tailscaleInfo->connectedViaTS() ? $tr->tr("yes") : $tr->tr("no"));
3536

3637
if ($tailscaleStatusInfo->LockInfo != null) {
3738
echo Utils::printRow("{$lockTranslate}: " . $tr->tr("info.lock.signed"), $tailscaleStatusInfo->LockInfo->LockSigned);

src/usr/local/emhttp/plugins/tailscale/include/Pages/Settings.php

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,20 @@
99
echo("Missing required WebGUI variables");
1010
return;
1111
}
12+
13+
// Used to disable buttons that should not be used over Tailscale since the connection will break.
14+
// (erase config, reauth, etc.)
15+
$tailscaleDisconnect = " disabled";
16+
17+
if ($tailscaleConfig->Enable) {
18+
$tailscaleInfo = $tailscaleInfo ?? new Info($tr);
19+
if ( ! $tailscaleInfo->connectedViaTS()) {
20+
$tailscaleDisconnect = "";
21+
}
22+
}
23+
1224
?>
25+
1326
<link type="text/css" rel="stylesheet" href="<?= Utils::auto_v('/webGui/styles/jquery.filetree.css');?>">
1427
<link type="text/css" rel="stylesheet" href="<?= Utils::auto_v('/webGui/styles/jquery.switchbutton.css');?>">
1528
<span class="status vhshift"><input type="checkbox" class="advancedview"></span>
@@ -157,14 +170,23 @@
157170
<?php } ?>
158171

159172
<div class="advanced">
173+
<h3><?= $tr->tr("settings.reauthenticate"); ?></h3>
174+
175+
<dl>
176+
<dt><?= $tr->tr("settings.context.reauthenticate"); ?></dt>
177+
<dd>
178+
<input type="button" value="<?= $tr->tr('settings.reauthenticate'); ?>" onclick="expireTailscaleKeyNow()" <?= $tailscaleDisconnect; ?>>
179+
</dd>
180+
</dl>
181+
160182
<h3><?= $tr->tr("settings.erase"); ?></h3>
161183

162184
<form method="POST" action="/update.php" target="progressFrame">
163185
<input type="hidden" name="#command" value="/usr/local/emhttp/plugins/tailscale/erase.sh">
164186
<dl>
165187
<dt><?= $tr->tr("settings.context.erase"); ?></dt>
166188
<dd>
167-
<input type="button" value="<?= $tr->tr('Erase'); ?>" onclick="requestErase(this)"><input id="tailscale_erase_confirm" type="submit" value="<?= $tr->tr('Confirm'); ?>" style="display: none;">
189+
<input type="button" value="<?= $tr->tr('Erase'); ?>" onclick="requestErase(this)" <?= $tailscaleDisconnect; ?>><input id="tailscale_erase_confirm" type="submit" value="<?= $tr->tr('Confirm'); ?>" style="display: none;">
168190
</dd>
169191
</dl>
170192
</form>
@@ -186,6 +208,12 @@ function requestErase(e) {
186208
var confirmButton = document.getElementById('tailscale_erase_confirm');
187209
confirmButton.style.display = "inline";
188210
}
211+
212+
async function expireTailscaleKeyNow() {
213+
$('div.spinner.fixed').show('fast');
214+
var res = await $.post('/plugins/tailscale/include/data/Config.php',{action: 'expire-key'});
215+
location.reload();
216+
}
189217
</script>
190218
<script>
191219
$(function() {

src/usr/local/emhttp/plugins/tailscale/include/Tailscale/Info.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ public function getExitNodes(): array
375375
{
376376
$exitNodes = array();
377377

378-
foreach ($this->status->Peer as $node => $status) {
378+
foreach (($this->status->Peer ?? array()) as $node => $status) {
379379
if ($status->ExitNodeOption ?? false) {
380380
$nodeName = $status->DNSName;
381381
if (isset($status->Location->City)) {
@@ -390,12 +390,17 @@ public function getExitNodes(): array
390390

391391
public function getCurrentExitNode(): string
392392
{
393-
foreach ($this->status->Peer as $node => $status) {
393+
foreach (($this->status->Peer ?? array()) as $node => $status) {
394394
if ($status->ExitNode ?? false) {
395395
return $status->ID;
396396
}
397397
}
398398

399399
return "";
400400
}
401+
402+
public function connectedViaTS(): bool
403+
{
404+
return in_array($_SERVER['SERVER_ADDR'] ?? "", $this->status->TailscaleIPs ?? array());
405+
}
401406
}

src/usr/local/emhttp/plugins/tailscale/include/Tailscale/LocalAPI.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,9 @@ public function postTkaSign(string $key): void
7979
$body = ["NodeKey" => $key];
8080
$this->tailscaleLocalAPI("v0/tka/sign", APIMethods::POST, (object) $body);
8181
}
82+
83+
public function expireKey(): void
84+
{
85+
$this->tailscaleLocalAPI('v0/set-expiry-sooner?expiry=0', APIMethods::POST);
86+
}
8287
}

src/usr/local/emhttp/plugins/tailscale/include/data/Config.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,13 @@
232232

233233
$localAPI->patchPref("AdvertiseRoutes", array_values($advertisedRoutes));
234234
break;
235+
case 'expire-key':
236+
if ($tailscaleInfo->connectedViaTS()) {
237+
throw new \Exception("Cannot expire key while connected via Tailscale");
238+
}
239+
Utils::logmsg("Expiring node key");
240+
$localAPI->expireKey();
241+
break;
235242
case 'exit-node':
236243
if ( ! isset($_POST['node'])) {
237244
throw new \Exception("Missing node parameter");

src/usr/local/emhttp/plugins/tailscale/locales/en_US.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"erase": "Erase Tailscale Configuration",
4545
"diagnostics": "Plugin Diagnostics",
4646
"donate": "Donate",
47+
"reauthenticate": "Reauthenticate",
4748
"context": {
4849
"unraid_listen": "Configures Unraid services (SSH, WebGUI, SMB, etc.) to listen on Tailscale addresses.",
4950
"ip_forward": "Sets net.ipv4.ip_forward and net.ipv6.conf.all.forwarding to 1 in sysctl. This change occurs immediately when being enabled.",
@@ -58,7 +59,8 @@
5859
"ignore": "If set to ignore, the plugin will not modify the setting",
5960
"outbound_network": "These settings only apply to outbound network traffic from Unraid or running containers. They do not affect advertised routes, exit nodes, or the ability to access Unraid via MagicDNS. These should generally be left off unless specifically needed. Turning these on may cause network issues.",
6061
"save": "Tailscale will be restarted when changes are applied",
61-
"donate": "If this plugin helps you, please consider donating."
62+
"donate": "If this plugin helps you, please consider donating.",
63+
"reauthenticate": "Force a Tailscale reauthentication. This will disconnect Tailscale until the authentication is completed."
6264
}
6365
},
6466
"help": {
@@ -97,6 +99,7 @@
9799
"use_exit_node": "Use Exit Node",
98100
"exit_node_local": "Allow LAN Access while using Exit Node",
99101
"unapproved": "Needs approval in admin console",
102+
"connected_via": "Connected via Tailscale",
100103
"lock": {
101104
"node_key": "Node Key",
102105
"public_key": "Public Key",

0 commit comments

Comments
 (0)