Skip to content

Commit 4d79e0d

Browse files
authored
feat: native configuration page (#30)
1 parent 9af7b7b commit 4d79e0d

File tree

13 files changed

+571
-119
lines changed

13 files changed

+571
-119
lines changed

src/usr/local/emhttp/plugins/tailscale/Tailscale.page

100755100644
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ Markdown="false"
1010
try {
1111
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
1212
require_once "{$docroot}/plugins/tailscale/include/page.php";
13-
echo Tailscale\getPage("Main");
13+
echo Tailscale\getPage("Tailscale");
1414
} catch (Throwable $e) {
1515
echo "An error occurred: <pre>" . print_r($e, true) . "</pre>";
1616
}
1717

18-
?>
18+
?>

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

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
$tailscaleInfo = $tailscaleInfo ?? new Info($tr);
1414
$tailscaleStatusInfo = $tailscaleInfo->getStatusInfo();
15-
$tailscaleConInfo = $tailscaleInfo->getConnectionInfo();
1615
?>
1716
<table class="unraid t1">
1817
<thead>
@@ -40,29 +39,6 @@
4039
echo Utils::printRow("{$lockTranslate}: " . $tr->tr("info.lock.node_key"), $tailscaleStatusInfo->LockInfo->NodeKey);
4140
echo Utils::printRow("{$lockTranslate}: " . $tr->tr("info.lock.public_key"), $tailscaleStatusInfo->LockInfo->PubKey);
4241
}
43-
?>
44-
</tbody>
45-
<tbody>
46-
<tr>
47-
<td>&nbsp;</td>
48-
<td>&nbsp;</td>
49-
</tr>
50-
</tbody>
51-
<thead>
52-
<tr>
53-
<td><?= $tr->tr('connection'); ?></td>
54-
<td>&nbsp;</td>
55-
</tr>
56-
</thead>
57-
<tbody>
58-
<?php
59-
echo Utils::printRow($tr->tr("info.hostname"), $tailscaleConInfo->HostName);
60-
echo Utils::printRow($tr->tr("info.dns"), $tailscaleConInfo->DNSName);
61-
echo Utils::printRow($tr->tr("info.ip"), $tailscaleConInfo->TailscaleIPs);
62-
echo Utils::printRow($tr->tr("info.magicdns"), $tailscaleConInfo->MagicDNSSuffix);
63-
echo Utils::printRow($tr->tr("info.routes"), $tailscaleConInfo->AdvertisedRoutes);
64-
echo Utils::printRow($tr->tr("info.accept_routes"), $tailscaleConInfo->AcceptRoutes);
65-
echo Utils::printRow($tr->tr("info.accept_dns"), $tailscaleConInfo->AcceptDNS);
6642
?>
6743
</tbody>
6844
</table>

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,4 @@
2222

2323
$tailscaleInfo = $tailscaleInfo ?? new Info($tr);
2424
?>
25-
<?= Utils::formatWarning($tailscaleInfo->getTailscaleLockWarning()); ?>
26-
<?= Utils::formatWarning($tailscaleInfo->getTailscaleNetbiosWarning()); ?>
27-
<?= Utils::formatWarning($tailscaleInfo->getKeyExpirationWarning()); ?>
28-
2925
<iframe src="/plugins/tailscale/interface.php" style="width:100%; height:600px; border: none;"></iframe>

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

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,8 @@
9494
<dt><?= $tr->tr("settings.subnets"); ?></dt>
9595
<dd>
9696
<select name='ACCEPT_ROUTES' size='1'>
97-
<?= Utils::make_option($tailscaleConfig->AcceptRoutes == 0, '0', $tr->tr("no"));?>
98-
<?= Utils::make_option($tailscaleConfig->AcceptRoutes == 1, '1', $tr->tr("yes"));?>
99-
<?= Utils::make_option($tailscaleConfig->AcceptRoutes == 2, '2', $tr->tr("ignore"));?>
97+
<?= Utils::make_option( ! $tailscaleConfig->AllowRoutes, '0', $tr->tr("no"));?>
98+
<?= Utils::make_option($tailscaleConfig->AllowRoutes, '1', $tr->tr("yes"));?>
10099
</select>
101100
</dd>
102101
</dl>
@@ -109,9 +108,8 @@
109108
<dt><?= $tr->tr("settings.dns"); ?></dt>
110109
<dd>
111110
<select name='ACCEPT_DNS' size='1'>
112-
<?= Utils::make_option($tailscaleConfig->AcceptDNS == 0, '0', $tr->tr("no"));?>
113-
<?= Utils::make_option($tailscaleConfig->AcceptDNS == 1, '1', $tr->tr("yes"));?>
114-
<?= Utils::make_option($tailscaleConfig->AcceptDNS == 2, '2', $tr->tr("ignore"));?>
111+
<?= Utils::make_option( ! $tailscaleConfig->AllowDNS, '0', $tr->tr("no"));?>
112+
<?= Utils::make_option($tailscaleConfig->AllowDNS, '1', $tr->tr("yes"));?>
115113
</select>
116114
</dd>
117115
</dl>
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
<?php
2+
3+
namespace Tailscale;
4+
5+
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
6+
require_once "{$docroot}/plugins/tailscale/include/common.php";
7+
8+
$tailscaleConfig = $tailscaleConfig ?? new Config();
9+
$tr = $tr ?? new Translator();
10+
11+
if ( ! $tailscaleConfig->Enable) {
12+
echo($tr->tr("tailscale_disabled"));
13+
return;
14+
}
15+
16+
$tailscaleInfo = $tailscaleInfo ?? new Info($tr);
17+
?>
18+
19+
<script src="/webGui/javascript/jquery.tablesorter.widgets.js"></script>
20+
21+
<script>
22+
23+
function tailscaleControlsDisabled(val) {
24+
$('#configTable_refresh').prop('disabled', val);
25+
}
26+
function showTailscaleConfig() {
27+
tailscaleControlsDisabled(true);
28+
$.post('/plugins/tailscale/include/data/Config.php',{action: 'get'},function(data){
29+
clearTimeout(timers.refresh);
30+
$("#configTable").trigger("destroy");
31+
$('#configTable').html(data.config);
32+
$("#routesTable").trigger("destroy");
33+
$('#routesTable').html(data.routes);
34+
$("#connectionTable").trigger("destroy");
35+
$('#connectionTable').html(data.connection);
36+
$('div.spinner.fixed').hide('fast');
37+
tailscaleControlsDisabled(false);
38+
validateTailscaleRoute();
39+
},"json");
40+
}
41+
async function setFeature(feature, enable) {
42+
$('div.spinner.fixed').show('fast');
43+
tailscaleControlsDisabled(true);
44+
var res = await $.post('/plugins/tailscale/include/data/Config.php',{action: 'set-feature', feature: feature, enable: enable});
45+
showTailscaleConfig();
46+
}
47+
async function tailscaleUp() {
48+
$('div.spinner.fixed').show('fast');
49+
tailscaleControlsDisabled(true);
50+
var res = await $.post('/plugins/tailscale/include/data/Config.php',{action: 'up'});
51+
$('#tailscaleUpLink').attr('href', res);
52+
$('#tailscaleUpLink').text(res);
53+
window.open(res);
54+
$('div.spinner.fixed').hide('fast');
55+
tailscaleControlsDisabled(false);
56+
}
57+
async function setTailscaleExitNode() {
58+
$('div.spinner.fixed').show('fast');
59+
tailscaleControlsDisabled(true);
60+
var res = await $.post('/plugins/tailscale/include/data/Config.php',{action: 'exit-node', node: $('#exitNodeSelect').val()});
61+
showTailscaleConfig();
62+
}
63+
64+
async function removeTailscaleRoute(route) {
65+
$('div.spinner.fixed').show('fast');
66+
tailscaleControlsDisabled(true);
67+
var res = await $.post('/plugins/tailscale/include/data/Config.php',{action: 'remove-route', route: route});
68+
showTailscaleConfig();
69+
}
70+
async function addTailscaleRoute() {
71+
$('div.spinner.fixed').show('fast');
72+
tailscaleControlsDisabled(true);
73+
var res = await $.post('/plugins/tailscale/include/data/Config.php',{action: 'add-route', route: $('#tailscaleRoute').val()});
74+
showTailscaleConfig();
75+
}
76+
function isValidCIDR(ip) {
77+
if (ip === undefined) {
78+
return false;
79+
}
80+
81+
var parts = ip.split('/');
82+
if (parts.length != 2) {
83+
return false;
84+
}
85+
86+
var mask = parseInt(parts[1]);
87+
if (isNaN(mask) || mask < 0) {
88+
return false;
89+
}
90+
91+
const ipv4Pattern = /^(\d{1,3}\.){3}\d{1,3}$/;
92+
const ipv6Pattern = /^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$/gm;
93+
94+
if(ipv4Pattern.test(parts[0])) {
95+
// IPv4
96+
if(mask > 32) {
97+
return false;
98+
}
99+
} else if (ipv6Pattern.test(parts[0])) {
100+
// IPv6
101+
if(mask > 128) {
102+
return false;
103+
}
104+
} else {
105+
return false;
106+
}
107+
108+
return true;
109+
}
110+
111+
function validateTailscaleRoute() {
112+
if (! $('#tailscaleRoute').length) {
113+
return;
114+
}
115+
116+
if (isValidCIDR($('#tailscaleRoute').val())) {
117+
$('#addTailscaleRoute').prop('disabled', false);
118+
} else {
119+
$('#addTailscaleRoute').prop('disabled', true);
120+
}
121+
}
122+
123+
showTailscaleConfig();
124+
</script>
125+
126+
<!-- TODO: Get these warnings with the table -->
127+
<?= Utils::formatWarning($tailscaleInfo->getTailscaleLockWarning()); ?>
128+
<?= Utils::formatWarning($tailscaleInfo->getTailscaleNetbiosWarning()); ?>
129+
<?= Utils::formatWarning($tailscaleInfo->getKeyExpirationWarning()); ?>
130+
131+
<table id='connectionTable' class="unraid statusTable tablesorter"><tr><td><div class="spinner"></div></td></tr></table><br>
132+
<table id='configTable' class="unraid statusTable tablesorter"><tr><td><div class="spinner"></div></td></tr></table><br>
133+
<table id='routesTable' class="unraid statusTable tablesorter"><tr><td><div class="spinner"></div></td></tr></table><br>
134+
<table>
135+
<tr>
136+
<td style="vertical-align: top">
137+
<input type="button" id="configTable_refresh" value="Refresh" onclick="showTailscaleConfig()">
138+
</td>
139+
</tr>
140+
</table>

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ class Config
99
public bool $IPForward;
1010
public bool $Enable;
1111
public bool $SSH;
12+
public bool $AllowDNS;
13+
public bool $AllowRoutes;
14+
1215
public int $WgPort;
13-
public int $AcceptDNS;
14-
public int $AcceptRoutes;
1516
public string $TaildropDir;
1617

1718
public function __construct()
@@ -30,10 +31,10 @@ public function __construct()
3031
$this->IPForward = boolval($saved_config["SYSCTL_IP_FORWARD"] ?? "1");
3132
$this->Enable = boolval($saved_config["ENABLE_TAILSCALE"] ?? "1");
3233
$this->SSH = boolval($saved_config["SSH"] ?? "0");
34+
$this->AllowDNS = boolval($saved_config["ACCEPT_DNS"] ?? "0");
35+
$this->AllowRoutes = boolval($saved_config["ACCEPT_ROUTES"] ?? "0");
3336

34-
$this->WgPort = intval($saved_config["WG_PORT"] ?? "0");
35-
$this->AcceptDNS = intval($saved_config["ACCEPT_DNS"] ?? "0");
36-
$this->AcceptRoutes = intval($saved_config["ACCEPT_ROUTES"] ?? "0");
37+
$this->WgPort = intval($saved_config["WG_PORT"] ?? "0");
3738

3839
$this->TaildropDir = $saved_config["TAILDROP_DIR"] ?? "";
3940
}

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

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44

55
class ConnectionInfo
66
{
7-
public string $HostName = "";
8-
public string $DNSName = "";
9-
public string $TailscaleIPs = "";
10-
public string $MagicDNSSuffix = "";
11-
public string $AdvertisedRoutes = "";
12-
public string $AcceptRoutes = "";
13-
public string $AcceptDNS = "";
7+
public string $HostName = "";
8+
public string $DNSName = "";
9+
public string $TailscaleIPs = "";
10+
public string $MagicDNSSuffix = "";
11+
public string $AdvertisedRoutes = "";
12+
public string $AcceptRoutes = "";
13+
public string $AcceptDNS = "";
14+
public string $RunSSH = "";
15+
public string $ExitNodeLocal = "";
16+
public string $AdvertiseExitNode = "";
17+
public string $UseExitNode = "";
1418
}

0 commit comments

Comments
 (0)