mirror of
https://github.com/Mo3he/Axis_Cam_Tailscale.git
synced 2026-07-20 14:52:19 +00:00
feat: add Accept DNS and Accept Routes toggles to all ACAP 4 variants
Restores the toggle implementation that shipped in the v1.96.4-dns-routes release but was never committed to main, so weekly auto-builds (v1.98.x) regressed and dropped the feature. - manifest.json: register AcceptDNS / AcceptRoutes parameters - param_bridge.c: cache, load, persist and live-reload the new params - Tailscale_VPN_run: append --accept-dns / --accept-routes when enabled; add --reset - html/index.html: add the Settings toggles
This commit is contained in:
@@ -18,6 +18,8 @@ CUSTOM_SERVER=""
|
||||
AUTH_KEY=""
|
||||
CONF_HTTP="8080"
|
||||
CONF_SOCKS="1080"
|
||||
ACCEPT_DNS="false"
|
||||
ACCEPT_ROUTES="false"
|
||||
|
||||
if [ -f "$STATE_DIR/params.conf" ]; then
|
||||
. "$STATE_DIR/params.conf"
|
||||
@@ -56,7 +58,7 @@ TAILSCALED_PID=$!
|
||||
|
||||
sleep 2
|
||||
|
||||
TAILSCALE_CMD="$TAILSCALE_PATH --socket=$SOCKET_PATH up --hostname=$(hostname)"
|
||||
TAILSCALE_CMD="$TAILSCALE_PATH --socket=$SOCKET_PATH up --reset --hostname=$(hostname)"
|
||||
|
||||
if [ -n "$CUSTOM_SERVER" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --login-server $CUSTOM_SERVER"
|
||||
@@ -66,6 +68,14 @@ if [ -n "$AUTH_KEY" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --authkey $AUTH_KEY"
|
||||
fi
|
||||
|
||||
if [ "$ACCEPT_DNS" = "true" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --accept-dns=true"
|
||||
fi
|
||||
|
||||
if [ "$ACCEPT_ROUTES" = "true" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --accept-routes=true"
|
||||
fi
|
||||
|
||||
eval $TAILSCALE_CMD
|
||||
UP_EXIT=$?
|
||||
|
||||
|
||||
@@ -272,6 +272,23 @@
|
||||
.save-status.ok { color: var(--green); }
|
||||
.save-status.err { color: var(--red); }
|
||||
|
||||
/* Toggle switch */
|
||||
.toggle-row { display: flex; align-items: flex-start; gap: 12px; }
|
||||
.toggle-switch { position: relative; width: 36px; height: 20px; flex-shrink: 0; margin-top: 2px; }
|
||||
.toggle-switch input { opacity: 0; width: 0; height: 0; position: absolute; }
|
||||
.toggle-slider {
|
||||
position: absolute; cursor: pointer; inset: 0;
|
||||
background: var(--border); border-radius: 20px; transition: background 0.2s;
|
||||
}
|
||||
.toggle-slider:before {
|
||||
content: ''; position: absolute;
|
||||
height: 14px; width: 14px; left: 3px; bottom: 3px;
|
||||
background: white; border-radius: 50%; transition: transform 0.2s;
|
||||
}
|
||||
.toggle-switch input:checked + .toggle-slider { background: var(--green); }
|
||||
.toggle-switch input:checked + .toggle-slider:before { transform: translateX(16px); }
|
||||
.toggle-info { flex: 1; }
|
||||
|
||||
/* Refresh indicator */
|
||||
.refresh-bar {
|
||||
display: flex;
|
||||
@@ -425,6 +442,26 @@
|
||||
<input class="settings-input" id="input-socks-port" type="text" autocomplete="off" placeholder="1080">
|
||||
<span class="settings-hint">Port for the SOCKS5 proxy. Default: 1080.</span>
|
||||
</div>
|
||||
<div class="settings-row toggle-row">
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="input-accept-dns">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
<div class="toggle-info">
|
||||
<div class="settings-label">Accept DNS</div>
|
||||
<span class="settings-hint">Pass <code>--accept-dns=true</code> to tailscale up. Allows the tailnet to push DNS settings to this device. Off by default to avoid overriding the camera's DNS configuration.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-row toggle-row">
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="input-accept-routes">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
<div class="toggle-info">
|
||||
<div class="settings-label">Accept Routes</div>
|
||||
<span class="settings-hint">Pass <code>--accept-routes=true</code> to tailscale up. Allows this device to use subnet routes advertised by other nodes in the tailnet.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-actions">
|
||||
<span class="save-status" id="save-status"></span>
|
||||
<button class="save-btn" id="save-btn">Save & Restart</button>
|
||||
@@ -779,6 +816,8 @@
|
||||
var authInput = document.getElementById('input-authkey');
|
||||
var httpPortInput = document.getElementById('input-http-port');
|
||||
var socksPortInput= document.getElementById('input-socks-port');
|
||||
var acceptDnsInput = document.getElementById('input-accept-dns');
|
||||
var acceptRoutesInput = document.getElementById('input-accept-routes');
|
||||
var saveBtn = document.getElementById('save-btn');
|
||||
var saveStatus = document.getElementById('save-status');
|
||||
|
||||
@@ -790,10 +829,14 @@
|
||||
var am = txt.match(/root\.\S+\.AuthKey=(.*)/);
|
||||
var hm = txt.match(/root\.\S+\.HttpProxyPort=(.*)/);
|
||||
var km = txt.match(/root\.\S+\.Socks5Port=(.*)/);
|
||||
var dm = txt.match(/root\.\S+\.AcceptDNS=(.*)/);
|
||||
var rm = txt.match(/root\.\S+\.AcceptRoutes=(.*)/);
|
||||
if (sm) serverInput.value = sm[1].trim();
|
||||
if (am) authInput.value = am[1].trim();
|
||||
if (hm) httpPortInput.value = hm[1].trim();
|
||||
if (km) socksPortInput.value = km[1].trim();
|
||||
if (dm) acceptDnsInput.checked = dm[1].trim() === 'true';
|
||||
if (rm) acceptRoutesInput.checked = rm[1].trim() === 'true';
|
||||
// Update proxy display card with authoritative param values
|
||||
// and overwrite the localStorage cache so stale ports don't win on next render
|
||||
var httpPort = hm ? hm[1].trim() : null;
|
||||
@@ -819,7 +862,9 @@
|
||||
'&root.' + APP + '.CustomServer=' + encodeURIComponent(serverInput.value.trim()) +
|
||||
'&root.' + APP + '.AuthKey=' + encodeURIComponent(authInput.value.trim()) +
|
||||
'&root.' + APP + '.HttpProxyPort=' + encodeURIComponent(httpPort) +
|
||||
'&root.' + APP + '.Socks5Port=' + encodeURIComponent(socksPort);
|
||||
'&root.' + APP + '.Socks5Port=' + encodeURIComponent(socksPort) +
|
||||
'&root.' + APP + '.AcceptDNS=' + (acceptDnsInput.checked ? 'true' : 'false') +
|
||||
'&root.' + APP + '.AcceptRoutes=' + (acceptRoutesInput.checked ? 'true' : 'false');
|
||||
fetch(PARAM_URL, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
|
||||
@@ -33,6 +33,16 @@
|
||||
"name": "Socks5Port",
|
||||
"default": "1080",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "AcceptDNS",
|
||||
"default": "false",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "AcceptRoutes",
|
||||
"default": "false",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -43,6 +43,8 @@ static char *cfg_custom_server = NULL;
|
||||
static char *cfg_auth_key = NULL;
|
||||
static char *cfg_http_proxy_port = NULL;
|
||||
static char *cfg_socks5_port = NULL;
|
||||
static char *cfg_accept_dns = NULL;
|
||||
static char *cfg_accept_routes = NULL;
|
||||
|
||||
static void cache_set(char **field, const char *value) {
|
||||
if (!value) return;
|
||||
@@ -139,6 +141,8 @@ static void load_config_cache(AXParameter *handle) {
|
||||
LOAD("AuthKey", cfg_auth_key)
|
||||
LOAD("HttpProxyPort", cfg_http_proxy_port)
|
||||
LOAD("Socks5Port", cfg_socks5_port)
|
||||
LOAD("AcceptDNS", cfg_accept_dns)
|
||||
LOAD("AcceptRoutes", cfg_accept_routes)
|
||||
#undef LOAD
|
||||
}
|
||||
|
||||
@@ -153,6 +157,8 @@ static void write_config_file(void) {
|
||||
fprintf(f, "AUTH_KEY=%s\n", cache_get(&cfg_auth_key, ""));
|
||||
fprintf(f, "CONF_HTTP=%s\n", cache_get(&cfg_http_proxy_port, "8080"));
|
||||
fprintf(f, "CONF_SOCKS=%s\n", cache_get(&cfg_socks5_port, "1080"));
|
||||
fprintf(f, "ACCEPT_DNS=%s\n", cache_get(&cfg_accept_dns, "false"));
|
||||
fprintf(f, "ACCEPT_ROUTES=%s\n", cache_get(&cfg_accept_routes, "false"));
|
||||
fclose(f);
|
||||
chmod(CONFIG_FILE, 0600);
|
||||
syslog(LOG_INFO, "config updated: http=%s socks=%s server=%s",
|
||||
@@ -185,6 +191,8 @@ static void parameter_changed(const gchar *name, const gchar *value,
|
||||
else if (strcmp(short_name, "AuthKey") == 0) cache_set(&cfg_auth_key, value);
|
||||
else if (strcmp(short_name, "HttpProxyPort") == 0) cache_set(&cfg_http_proxy_port, value);
|
||||
else if (strcmp(short_name, "Socks5Port") == 0) cache_set(&cfg_socks5_port, value);
|
||||
else if (strcmp(short_name, "AcceptDNS") == 0) cache_set(&cfg_accept_dns, value);
|
||||
else if (strcmp(short_name, "AcceptRoutes") == 0) cache_set(&cfg_accept_routes, value);
|
||||
|
||||
if (reload_timer_id)
|
||||
g_source_remove(reload_timer_id);
|
||||
@@ -225,7 +233,8 @@ int main(void) {
|
||||
start_child();
|
||||
|
||||
const char *params[] = {
|
||||
"CustomServer", "AuthKey", "HttpProxyPort", "Socks5Port"
|
||||
"CustomServer", "AuthKey", "HttpProxyPort", "Socks5Port",
|
||||
"AcceptDNS", "AcceptRoutes"
|
||||
};
|
||||
for (size_t i = 0; i < sizeof(params) / sizeof(params[0]); i++) {
|
||||
if (!ax_parameter_register_callback(handle, params[i],
|
||||
|
||||
@@ -15,6 +15,8 @@ chmod 755 $TAILSCALE_PATH
|
||||
|
||||
CUSTOM_SERVER=""
|
||||
AUTH_KEY=""
|
||||
ACCEPT_DNS="false"
|
||||
ACCEPT_ROUTES="false"
|
||||
|
||||
if [ -f "$STATE_DIR/params.conf" ]; then
|
||||
. "$STATE_DIR/params.conf"
|
||||
@@ -30,7 +32,7 @@ TAILSCALED_PID=$!
|
||||
|
||||
sleep 2
|
||||
|
||||
TAILSCALE_CMD="$TAILSCALE_PATH --socket=$SOCKET_PATH up --accept-routes --hostname=$(hostname)"
|
||||
TAILSCALE_CMD="$TAILSCALE_PATH --socket=$SOCKET_PATH up --reset --hostname=$(hostname)"
|
||||
|
||||
if [ -n "$CUSTOM_SERVER" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --login-server $CUSTOM_SERVER"
|
||||
@@ -40,6 +42,14 @@ if [ -n "$AUTH_KEY" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --authkey $AUTH_KEY"
|
||||
fi
|
||||
|
||||
if [ "$ACCEPT_DNS" = "true" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --accept-dns=true"
|
||||
fi
|
||||
|
||||
if [ "$ACCEPT_ROUTES" = "true" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --accept-routes=true"
|
||||
fi
|
||||
|
||||
eval $TAILSCALE_CMD
|
||||
UP_EXIT=$?
|
||||
|
||||
|
||||
@@ -272,6 +272,23 @@
|
||||
.save-status.ok { color: var(--green); }
|
||||
.save-status.err { color: var(--red); }
|
||||
|
||||
/* Toggle switch */
|
||||
.toggle-row { display: flex; align-items: flex-start; gap: 12px; }
|
||||
.toggle-switch { position: relative; width: 36px; height: 20px; flex-shrink: 0; margin-top: 2px; }
|
||||
.toggle-switch input { opacity: 0; width: 0; height: 0; position: absolute; }
|
||||
.toggle-slider {
|
||||
position: absolute; cursor: pointer; inset: 0;
|
||||
background: var(--border); border-radius: 20px; transition: background 0.2s;
|
||||
}
|
||||
.toggle-slider:before {
|
||||
content: ''; position: absolute;
|
||||
height: 14px; width: 14px; left: 3px; bottom: 3px;
|
||||
background: white; border-radius: 50%; transition: transform 0.2s;
|
||||
}
|
||||
.toggle-switch input:checked + .toggle-slider { background: var(--green); }
|
||||
.toggle-switch input:checked + .toggle-slider:before { transform: translateX(16px); }
|
||||
.toggle-info { flex: 1; }
|
||||
|
||||
/* Refresh indicator */
|
||||
.refresh-bar {
|
||||
display: flex;
|
||||
@@ -425,6 +442,26 @@
|
||||
<input class="settings-input" id="input-socks-port" type="text" autocomplete="off" placeholder="1080">
|
||||
<span class="settings-hint">Port for the SOCKS5 proxy. Default: 1080.</span>
|
||||
</div>
|
||||
<div class="settings-row toggle-row">
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="input-accept-dns">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
<div class="toggle-info">
|
||||
<div class="settings-label">Accept DNS</div>
|
||||
<span class="settings-hint">Pass <code>--accept-dns=true</code> to tailscale up. Allows the tailnet to push DNS settings to this device. Off by default to avoid overriding the camera's DNS configuration.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-row toggle-row">
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="input-accept-routes">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
<div class="toggle-info">
|
||||
<div class="settings-label">Accept Routes</div>
|
||||
<span class="settings-hint">Pass <code>--accept-routes=true</code> to tailscale up. Allows this device to use subnet routes advertised by other nodes in the tailnet.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-actions">
|
||||
<span class="save-status" id="save-status"></span>
|
||||
<button class="save-btn" id="save-btn">Save & Restart</button>
|
||||
@@ -779,6 +816,8 @@
|
||||
var authInput = document.getElementById('input-authkey');
|
||||
var httpPortInput = document.getElementById('input-http-port');
|
||||
var socksPortInput= document.getElementById('input-socks-port');
|
||||
var acceptDnsInput = document.getElementById('input-accept-dns');
|
||||
var acceptRoutesInput = document.getElementById('input-accept-routes');
|
||||
var saveBtn = document.getElementById('save-btn');
|
||||
var saveStatus = document.getElementById('save-status');
|
||||
|
||||
@@ -790,10 +829,14 @@
|
||||
var am = txt.match(/root\.\S+\.AuthKey=(.*)/);
|
||||
var hm = txt.match(/root\.\S+\.HttpProxyPort=(.*)/);
|
||||
var km = txt.match(/root\.\S+\.Socks5Port=(.*)/);
|
||||
var dm = txt.match(/root\.\S+\.AcceptDNS=(.*)/);
|
||||
var rm = txt.match(/root\.\S+\.AcceptRoutes=(.*)/);
|
||||
if (sm) serverInput.value = sm[1].trim();
|
||||
if (am) authInput.value = am[1].trim();
|
||||
if (hm) httpPortInput.value = hm[1].trim();
|
||||
if (km) socksPortInput.value = km[1].trim();
|
||||
if (dm) acceptDnsInput.checked = dm[1].trim() === 'true';
|
||||
if (rm) acceptRoutesInput.checked = rm[1].trim() === 'true';
|
||||
// Update proxy display card with authoritative param values
|
||||
// and overwrite the localStorage cache so stale ports don't win on next render
|
||||
var httpPort = hm ? hm[1].trim() : null;
|
||||
@@ -819,7 +862,9 @@
|
||||
'&root.' + APP + '.CustomServer=' + encodeURIComponent(serverInput.value.trim()) +
|
||||
'&root.' + APP + '.AuthKey=' + encodeURIComponent(authInput.value.trim()) +
|
||||
'&root.' + APP + '.HttpProxyPort=' + encodeURIComponent(httpPort) +
|
||||
'&root.' + APP + '.Socks5Port=' + encodeURIComponent(socksPort);
|
||||
'&root.' + APP + '.Socks5Port=' + encodeURIComponent(socksPort) +
|
||||
'&root.' + APP + '.AcceptDNS=' + (acceptDnsInput.checked ? 'true' : 'false') +
|
||||
'&root.' + APP + '.AcceptRoutes=' + (acceptRoutesInput.checked ? 'true' : 'false');
|
||||
fetch(PARAM_URL, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
|
||||
@@ -27,6 +27,16 @@
|
||||
"name": "AuthKey",
|
||||
"default": "",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "AcceptDNS",
|
||||
"default": "false",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "AcceptRoutes",
|
||||
"default": "false",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ static guint reload_timer_id = 0;
|
||||
|
||||
static char *cfg_custom_server = NULL;
|
||||
static char *cfg_auth_key = NULL;
|
||||
static char *cfg_accept_dns = NULL;
|
||||
static char *cfg_accept_routes = NULL;
|
||||
|
||||
static void cache_set(char **field, const char *value) {
|
||||
if (!value) return;
|
||||
@@ -119,6 +121,8 @@ static void load_config_cache(AXParameter *handle) {
|
||||
|
||||
LOAD("CustomServer", cfg_custom_server)
|
||||
LOAD("AuthKey", cfg_auth_key)
|
||||
LOAD("AcceptDNS", cfg_accept_dns)
|
||||
LOAD("AcceptRoutes", cfg_accept_routes)
|
||||
#undef LOAD
|
||||
}
|
||||
|
||||
@@ -131,6 +135,8 @@ static void write_config_file(void) {
|
||||
}
|
||||
fprintf(f, "CUSTOM_SERVER=%s\n", cache_get(&cfg_custom_server, ""));
|
||||
fprintf(f, "AUTH_KEY=%s\n", cache_get(&cfg_auth_key, ""));
|
||||
fprintf(f, "ACCEPT_DNS=%s\n", cache_get(&cfg_accept_dns, "false"));
|
||||
fprintf(f, "ACCEPT_ROUTES=%s\n", cache_get(&cfg_accept_routes, "false"));
|
||||
fclose(f);
|
||||
chmod(CONFIG_FILE, 0600);
|
||||
syslog(LOG_INFO, "config updated: server=%s",
|
||||
@@ -156,6 +162,8 @@ static void parameter_changed(const gchar *name, const gchar *value,
|
||||
|
||||
if (strcmp(short_name, "CustomServer") == 0) cache_set(&cfg_custom_server, value);
|
||||
else if (strcmp(short_name, "AuthKey") == 0) cache_set(&cfg_auth_key, value);
|
||||
else if (strcmp(short_name, "AcceptDNS") == 0) cache_set(&cfg_accept_dns, value);
|
||||
else if (strcmp(short_name, "AcceptRoutes") == 0) cache_set(&cfg_accept_routes, value);
|
||||
|
||||
if (reload_timer_id)
|
||||
g_source_remove(reload_timer_id);
|
||||
@@ -190,7 +198,7 @@ int main(void) {
|
||||
write_config_file();
|
||||
start_child();
|
||||
|
||||
const char *params[] = { "CustomServer", "AuthKey" };
|
||||
const char *params[] = { "CustomServer", "AuthKey", "AcceptDNS", "AcceptRoutes" };
|
||||
for (size_t i = 0; i < sizeof(params) / sizeof(params[0]); i++) {
|
||||
if (!ax_parameter_register_callback(handle, params[i],
|
||||
parameter_changed, handle, &error)) {
|
||||
|
||||
@@ -18,6 +18,8 @@ CUSTOM_SERVER=""
|
||||
AUTH_KEY=""
|
||||
CONF_HTTP="8080"
|
||||
CONF_SOCKS="1080"
|
||||
ACCEPT_DNS="false"
|
||||
ACCEPT_ROUTES="false"
|
||||
|
||||
if [ -f "$STATE_DIR/params.conf" ]; then
|
||||
. "$STATE_DIR/params.conf"
|
||||
@@ -56,7 +58,7 @@ TAILSCALED_PID=$!
|
||||
|
||||
sleep 2
|
||||
|
||||
TAILSCALE_CMD="$TAILSCALE_PATH --socket=$SOCKET_PATH up --hostname=$(hostname)"
|
||||
TAILSCALE_CMD="$TAILSCALE_PATH --socket=$SOCKET_PATH up --reset --hostname=$(hostname)"
|
||||
|
||||
if [ -n "$CUSTOM_SERVER" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --login-server $CUSTOM_SERVER"
|
||||
@@ -66,6 +68,14 @@ if [ -n "$AUTH_KEY" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --authkey $AUTH_KEY"
|
||||
fi
|
||||
|
||||
if [ "$ACCEPT_DNS" = "true" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --accept-dns=true"
|
||||
fi
|
||||
|
||||
if [ "$ACCEPT_ROUTES" = "true" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --accept-routes=true"
|
||||
fi
|
||||
|
||||
eval $TAILSCALE_CMD
|
||||
UP_EXIT=$?
|
||||
|
||||
|
||||
+46
-1
@@ -272,6 +272,23 @@
|
||||
.save-status.ok { color: var(--green); }
|
||||
.save-status.err { color: var(--red); }
|
||||
|
||||
/* Toggle switch */
|
||||
.toggle-row { display: flex; align-items: flex-start; gap: 12px; }
|
||||
.toggle-switch { position: relative; width: 36px; height: 20px; flex-shrink: 0; margin-top: 2px; }
|
||||
.toggle-switch input { opacity: 0; width: 0; height: 0; position: absolute; }
|
||||
.toggle-slider {
|
||||
position: absolute; cursor: pointer; inset: 0;
|
||||
background: var(--border); border-radius: 20px; transition: background 0.2s;
|
||||
}
|
||||
.toggle-slider:before {
|
||||
content: ''; position: absolute;
|
||||
height: 14px; width: 14px; left: 3px; bottom: 3px;
|
||||
background: white; border-radius: 50%; transition: transform 0.2s;
|
||||
}
|
||||
.toggle-switch input:checked + .toggle-slider { background: var(--green); }
|
||||
.toggle-switch input:checked + .toggle-slider:before { transform: translateX(16px); }
|
||||
.toggle-info { flex: 1; }
|
||||
|
||||
/* Refresh indicator */
|
||||
.refresh-bar {
|
||||
display: flex;
|
||||
@@ -425,6 +442,26 @@
|
||||
<input class="settings-input" id="input-socks-port" type="text" autocomplete="off" placeholder="1080">
|
||||
<span class="settings-hint">Port for the SOCKS5 proxy. Default: 1080.</span>
|
||||
</div>
|
||||
<div class="settings-row toggle-row">
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="input-accept-dns">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
<div class="toggle-info">
|
||||
<div class="settings-label">Accept DNS</div>
|
||||
<span class="settings-hint">Pass <code>--accept-dns=true</code> to tailscale up. Allows the tailnet to push DNS settings to this device. Off by default to avoid overriding the camera's DNS configuration.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-row toggle-row">
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="input-accept-routes">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
<div class="toggle-info">
|
||||
<div class="settings-label">Accept Routes</div>
|
||||
<span class="settings-hint">Pass <code>--accept-routes=true</code> to tailscale up. Allows this device to use subnet routes advertised by other nodes in the tailnet.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-actions">
|
||||
<span class="save-status" id="save-status"></span>
|
||||
<button class="save-btn" id="save-btn">Save & Restart</button>
|
||||
@@ -779,6 +816,8 @@
|
||||
var authInput = document.getElementById('input-authkey');
|
||||
var httpPortInput = document.getElementById('input-http-port');
|
||||
var socksPortInput= document.getElementById('input-socks-port');
|
||||
var acceptDnsInput = document.getElementById('input-accept-dns');
|
||||
var acceptRoutesInput = document.getElementById('input-accept-routes');
|
||||
var saveBtn = document.getElementById('save-btn');
|
||||
var saveStatus = document.getElementById('save-status');
|
||||
|
||||
@@ -790,10 +829,14 @@
|
||||
var am = txt.match(/root\.\S+\.AuthKey=(.*)/);
|
||||
var hm = txt.match(/root\.\S+\.HttpProxyPort=(.*)/);
|
||||
var km = txt.match(/root\.\S+\.Socks5Port=(.*)/);
|
||||
var dm = txt.match(/root\.\S+\.AcceptDNS=(.*)/);
|
||||
var rm = txt.match(/root\.\S+\.AcceptRoutes=(.*)/);
|
||||
if (sm) serverInput.value = sm[1].trim();
|
||||
if (am) authInput.value = am[1].trim();
|
||||
if (hm) httpPortInput.value = hm[1].trim();
|
||||
if (km) socksPortInput.value = km[1].trim();
|
||||
if (dm) acceptDnsInput.checked = dm[1].trim() === 'true';
|
||||
if (rm) acceptRoutesInput.checked = rm[1].trim() === 'true';
|
||||
// Update proxy display card with authoritative param values
|
||||
// and overwrite the localStorage cache so stale ports don't win on next render
|
||||
var httpPort = hm ? hm[1].trim() : null;
|
||||
@@ -819,7 +862,9 @@
|
||||
'&root.' + APP + '.CustomServer=' + encodeURIComponent(serverInput.value.trim()) +
|
||||
'&root.' + APP + '.AuthKey=' + encodeURIComponent(authInput.value.trim()) +
|
||||
'&root.' + APP + '.HttpProxyPort=' + encodeURIComponent(httpPort) +
|
||||
'&root.' + APP + '.Socks5Port=' + encodeURIComponent(socksPort);
|
||||
'&root.' + APP + '.Socks5Port=' + encodeURIComponent(socksPort) +
|
||||
'&root.' + APP + '.AcceptDNS=' + (acceptDnsInput.checked ? 'true' : 'false') +
|
||||
'&root.' + APP + '.AcceptRoutes=' + (acceptRoutesInput.checked ? 'true' : 'false');
|
||||
fetch(PARAM_URL, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
|
||||
@@ -33,6 +33,16 @@
|
||||
"name": "Socks5Port",
|
||||
"default": "1080",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "AcceptDNS",
|
||||
"default": "false",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "AcceptRoutes",
|
||||
"default": "false",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+10
-1
@@ -43,6 +43,8 @@ static char *cfg_custom_server = NULL;
|
||||
static char *cfg_auth_key = NULL;
|
||||
static char *cfg_http_proxy_port = NULL;
|
||||
static char *cfg_socks5_port = NULL;
|
||||
static char *cfg_accept_dns = NULL;
|
||||
static char *cfg_accept_routes = NULL;
|
||||
|
||||
static void cache_set(char **field, const char *value) {
|
||||
if (!value) return;
|
||||
@@ -139,6 +141,8 @@ static void load_config_cache(AXParameter *handle) {
|
||||
LOAD("AuthKey", cfg_auth_key)
|
||||
LOAD("HttpProxyPort", cfg_http_proxy_port)
|
||||
LOAD("Socks5Port", cfg_socks5_port)
|
||||
LOAD("AcceptDNS", cfg_accept_dns)
|
||||
LOAD("AcceptRoutes", cfg_accept_routes)
|
||||
#undef LOAD
|
||||
}
|
||||
|
||||
@@ -153,6 +157,8 @@ static void write_config_file(void) {
|
||||
fprintf(f, "AUTH_KEY=%s\n", cache_get(&cfg_auth_key, ""));
|
||||
fprintf(f, "CONF_HTTP=%s\n", cache_get(&cfg_http_proxy_port, "8080"));
|
||||
fprintf(f, "CONF_SOCKS=%s\n", cache_get(&cfg_socks5_port, "1080"));
|
||||
fprintf(f, "ACCEPT_DNS=%s\n", cache_get(&cfg_accept_dns, "false"));
|
||||
fprintf(f, "ACCEPT_ROUTES=%s\n", cache_get(&cfg_accept_routes, "false"));
|
||||
fclose(f);
|
||||
chmod(CONFIG_FILE, 0600);
|
||||
syslog(LOG_INFO, "config updated: http=%s socks=%s server=%s",
|
||||
@@ -185,6 +191,8 @@ static void parameter_changed(const gchar *name, const gchar *value,
|
||||
else if (strcmp(short_name, "AuthKey") == 0) cache_set(&cfg_auth_key, value);
|
||||
else if (strcmp(short_name, "HttpProxyPort") == 0) cache_set(&cfg_http_proxy_port, value);
|
||||
else if (strcmp(short_name, "Socks5Port") == 0) cache_set(&cfg_socks5_port, value);
|
||||
else if (strcmp(short_name, "AcceptDNS") == 0) cache_set(&cfg_accept_dns, value);
|
||||
else if (strcmp(short_name, "AcceptRoutes") == 0) cache_set(&cfg_accept_routes, value);
|
||||
|
||||
if (reload_timer_id)
|
||||
g_source_remove(reload_timer_id);
|
||||
@@ -225,7 +233,8 @@ int main(void) {
|
||||
start_child();
|
||||
|
||||
const char *params[] = {
|
||||
"CustomServer", "AuthKey", "HttpProxyPort", "Socks5Port"
|
||||
"CustomServer", "AuthKey", "HttpProxyPort", "Socks5Port",
|
||||
"AcceptDNS", "AcceptRoutes"
|
||||
};
|
||||
for (size_t i = 0; i < sizeof(params) / sizeof(params[0]); i++) {
|
||||
if (!ax_parameter_register_callback(handle, params[i],
|
||||
|
||||
@@ -15,6 +15,8 @@ chmod 755 $TAILSCALE_PATH
|
||||
|
||||
CUSTOM_SERVER=""
|
||||
AUTH_KEY=""
|
||||
ACCEPT_DNS="false"
|
||||
ACCEPT_ROUTES="false"
|
||||
|
||||
if [ -f "$STATE_DIR/params.conf" ]; then
|
||||
. "$STATE_DIR/params.conf"
|
||||
@@ -30,7 +32,7 @@ TAILSCALED_PID=$!
|
||||
|
||||
sleep 2
|
||||
|
||||
TAILSCALE_CMD="$TAILSCALE_PATH --socket=$SOCKET_PATH up --accept-routes --hostname=$(hostname)"
|
||||
TAILSCALE_CMD="$TAILSCALE_PATH --socket=$SOCKET_PATH up --reset --hostname=$(hostname)"
|
||||
|
||||
if [ -n "$CUSTOM_SERVER" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --login-server $CUSTOM_SERVER"
|
||||
@@ -40,6 +42,14 @@ if [ -n "$AUTH_KEY" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --authkey $AUTH_KEY"
|
||||
fi
|
||||
|
||||
if [ "$ACCEPT_DNS" = "true" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --accept-dns=true"
|
||||
fi
|
||||
|
||||
if [ "$ACCEPT_ROUTES" = "true" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --accept-routes=true"
|
||||
fi
|
||||
|
||||
eval $TAILSCALE_CMD
|
||||
UP_EXIT=$?
|
||||
|
||||
|
||||
@@ -272,6 +272,23 @@
|
||||
.save-status.ok { color: var(--green); }
|
||||
.save-status.err { color: var(--red); }
|
||||
|
||||
/* Toggle switch */
|
||||
.toggle-row { display: flex; align-items: flex-start; gap: 12px; }
|
||||
.toggle-switch { position: relative; width: 36px; height: 20px; flex-shrink: 0; margin-top: 2px; }
|
||||
.toggle-switch input { opacity: 0; width: 0; height: 0; position: absolute; }
|
||||
.toggle-slider {
|
||||
position: absolute; cursor: pointer; inset: 0;
|
||||
background: var(--border); border-radius: 20px; transition: background 0.2s;
|
||||
}
|
||||
.toggle-slider:before {
|
||||
content: ''; position: absolute;
|
||||
height: 14px; width: 14px; left: 3px; bottom: 3px;
|
||||
background: white; border-radius: 50%; transition: transform 0.2s;
|
||||
}
|
||||
.toggle-switch input:checked + .toggle-slider { background: var(--green); }
|
||||
.toggle-switch input:checked + .toggle-slider:before { transform: translateX(16px); }
|
||||
.toggle-info { flex: 1; }
|
||||
|
||||
/* Refresh indicator */
|
||||
.refresh-bar {
|
||||
display: flex;
|
||||
@@ -425,6 +442,26 @@
|
||||
<input class="settings-input" id="input-socks-port" type="text" autocomplete="off" placeholder="1080">
|
||||
<span class="settings-hint">Port for the SOCKS5 proxy. Default: 1080.</span>
|
||||
</div>
|
||||
<div class="settings-row toggle-row">
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="input-accept-dns">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
<div class="toggle-info">
|
||||
<div class="settings-label">Accept DNS</div>
|
||||
<span class="settings-hint">Pass <code>--accept-dns=true</code> to tailscale up. Allows the tailnet to push DNS settings to this device. Off by default to avoid overriding the camera's DNS configuration.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-row toggle-row">
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="input-accept-routes">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
<div class="toggle-info">
|
||||
<div class="settings-label">Accept Routes</div>
|
||||
<span class="settings-hint">Pass <code>--accept-routes=true</code> to tailscale up. Allows this device to use subnet routes advertised by other nodes in the tailnet.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-actions">
|
||||
<span class="save-status" id="save-status"></span>
|
||||
<button class="save-btn" id="save-btn">Save & Restart</button>
|
||||
@@ -779,6 +816,8 @@
|
||||
var authInput = document.getElementById('input-authkey');
|
||||
var httpPortInput = document.getElementById('input-http-port');
|
||||
var socksPortInput= document.getElementById('input-socks-port');
|
||||
var acceptDnsInput = document.getElementById('input-accept-dns');
|
||||
var acceptRoutesInput = document.getElementById('input-accept-routes');
|
||||
var saveBtn = document.getElementById('save-btn');
|
||||
var saveStatus = document.getElementById('save-status');
|
||||
|
||||
@@ -790,10 +829,14 @@
|
||||
var am = txt.match(/root\.\S+\.AuthKey=(.*)/);
|
||||
var hm = txt.match(/root\.\S+\.HttpProxyPort=(.*)/);
|
||||
var km = txt.match(/root\.\S+\.Socks5Port=(.*)/);
|
||||
var dm = txt.match(/root\.\S+\.AcceptDNS=(.*)/);
|
||||
var rm = txt.match(/root\.\S+\.AcceptRoutes=(.*)/);
|
||||
if (sm) serverInput.value = sm[1].trim();
|
||||
if (am) authInput.value = am[1].trim();
|
||||
if (hm) httpPortInput.value = hm[1].trim();
|
||||
if (km) socksPortInput.value = km[1].trim();
|
||||
if (dm) acceptDnsInput.checked = dm[1].trim() === 'true';
|
||||
if (rm) acceptRoutesInput.checked = rm[1].trim() === 'true';
|
||||
// Update proxy display card with authoritative param values
|
||||
// and overwrite the localStorage cache so stale ports don't win on next render
|
||||
var httpPort = hm ? hm[1].trim() : null;
|
||||
@@ -819,7 +862,9 @@
|
||||
'&root.' + APP + '.CustomServer=' + encodeURIComponent(serverInput.value.trim()) +
|
||||
'&root.' + APP + '.AuthKey=' + encodeURIComponent(authInput.value.trim()) +
|
||||
'&root.' + APP + '.HttpProxyPort=' + encodeURIComponent(httpPort) +
|
||||
'&root.' + APP + '.Socks5Port=' + encodeURIComponent(socksPort);
|
||||
'&root.' + APP + '.Socks5Port=' + encodeURIComponent(socksPort) +
|
||||
'&root.' + APP + '.AcceptDNS=' + (acceptDnsInput.checked ? 'true' : 'false') +
|
||||
'&root.' + APP + '.AcceptRoutes=' + (acceptRoutesInput.checked ? 'true' : 'false');
|
||||
fetch(PARAM_URL, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
|
||||
@@ -27,6 +27,16 @@
|
||||
"name": "AuthKey",
|
||||
"default": "",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "AcceptDNS",
|
||||
"default": "false",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "AcceptRoutes",
|
||||
"default": "false",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ static AXParameter *g_ax_handle = NULL;
|
||||
|
||||
static char *cfg_custom_server = NULL;
|
||||
static char *cfg_auth_key = NULL;
|
||||
static char *cfg_accept_dns = NULL;
|
||||
static char *cfg_accept_routes = NULL;
|
||||
|
||||
static void cache_set(char **field, const char *value) {
|
||||
if (!value) return;
|
||||
@@ -119,6 +121,8 @@ static void load_config_cache(AXParameter *handle) {
|
||||
|
||||
LOAD("CustomServer", cfg_custom_server)
|
||||
LOAD("AuthKey", cfg_auth_key)
|
||||
LOAD("AcceptDNS", cfg_accept_dns)
|
||||
LOAD("AcceptRoutes", cfg_accept_routes)
|
||||
#undef LOAD
|
||||
}
|
||||
|
||||
@@ -131,6 +135,8 @@ static void write_config_file(void) {
|
||||
}
|
||||
fprintf(f, "CUSTOM_SERVER=%s\n", cache_get(&cfg_custom_server, ""));
|
||||
fprintf(f, "AUTH_KEY=%s\n", cache_get(&cfg_auth_key, ""));
|
||||
fprintf(f, "ACCEPT_DNS=%s\n", cache_get(&cfg_accept_dns, "false"));
|
||||
fprintf(f, "ACCEPT_ROUTES=%s\n", cache_get(&cfg_accept_routes, "false"));
|
||||
fclose(f);
|
||||
chmod(CONFIG_FILE, 0600);
|
||||
syslog(LOG_INFO, "config updated: server=%s",
|
||||
@@ -156,6 +162,8 @@ static void parameter_changed(const gchar *name, const gchar *value,
|
||||
|
||||
if (strcmp(short_name, "CustomServer") == 0) cache_set(&cfg_custom_server, value);
|
||||
else if (strcmp(short_name, "AuthKey") == 0) cache_set(&cfg_auth_key, value);
|
||||
else if (strcmp(short_name, "AcceptDNS") == 0) cache_set(&cfg_accept_dns, value);
|
||||
else if (strcmp(short_name, "AcceptRoutes") == 0) cache_set(&cfg_accept_routes, value);
|
||||
|
||||
if (reload_timer_id)
|
||||
g_source_remove(reload_timer_id);
|
||||
@@ -190,7 +198,7 @@ int main(void) {
|
||||
write_config_file();
|
||||
start_child();
|
||||
|
||||
const char *params[] = { "CustomServer", "AuthKey" };
|
||||
const char *params[] = { "CustomServer", "AuthKey", "AcceptDNS", "AcceptRoutes" };
|
||||
for (size_t i = 0; i < sizeof(params) / sizeof(params[0]); i++) {
|
||||
if (!ax_parameter_register_callback(handle, params[i],
|
||||
parameter_changed, handle, &error)) {
|
||||
|
||||
Reference in New Issue
Block a user