Fix modern DNS startup and parameterize node provisioning
This commit is contained in:
parent
12d9f2b47c
commit
3b72c3e3c1
@ -2,7 +2,7 @@
|
|||||||
require getcwd() . '/vendor/autoload.php';
|
require getcwd() . '/vendor/autoload.php';
|
||||||
$app = require getcwd() . '/bootstrap/app.php';
|
$app = require getcwd() . '/bootstrap/app.php';
|
||||||
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
|
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
|
||||||
$opts = getopt('', ['backup:']);
|
$opts = getopt('', ['backup:', 'expected-current-sha256:']);
|
||||||
$dir = $opts['backup'] ?? throw new RuntimeException('Missing backup');
|
$dir = $opts['backup'] ?? throw new RuntimeException('Missing backup');
|
||||||
umask(0077);
|
umask(0077);
|
||||||
$old = App\Models\SubscribeTemplate::where('name', 'singbox')->firstOrFail();
|
$old = App\Models\SubscribeTemplate::where('name', 'singbox')->firstOrFail();
|
||||||
@ -11,9 +11,11 @@ $replacement = file_get_contents(__DIR__ . '/sing-box-template.json');
|
|||||||
$new = json_decode($replacement, true, flags: JSON_THROW_ON_ERROR);
|
$new = json_decode($replacement, true, flags: JSON_THROW_ON_ERROR);
|
||||||
$current = json_decode($old->content, true, flags: JSON_THROW_ON_ERROR);
|
$current = json_decode($old->content, true, flags: JSON_THROW_ON_ERROR);
|
||||||
if ($current === $new) { echo "Template already updated\n"; exit; }
|
if ($current === $new) { echo "Template already updated\n"; exit; }
|
||||||
if ($current !== $default) throw new RuntimeException('Custom template detected; inspect instead of overwriting');
|
$expected = $opts['expected-current-sha256'] ?? '';
|
||||||
|
$knownRevision = preg_match('/^[a-f0-9]{64}$/', $expected) && hash_equals($expected, hash('sha256', $old->content));
|
||||||
|
if ($current !== $default && !$knownRevision) throw new RuntimeException('Custom or unexpected template detected; inspect instead of overwriting');
|
||||||
if (!is_dir($dir)) throw new RuntimeException('Backup directory missing');
|
if (!is_dir($dir)) throw new RuntimeException('Backup directory missing');
|
||||||
$path = "$dir/singbox-template-before.json";
|
$path = "$dir/singbox-template-before-" . hash('sha256', $old->content) . '.json';
|
||||||
if (is_file($path)) throw new RuntimeException('Existing backup; inspect before retry');
|
if (is_file($path)) throw new RuntimeException('Existing backup; inspect before retry');
|
||||||
file_put_contents($path, json_encode($old->getAttributes(), JSON_THROW_ON_ERROR));
|
file_put_contents($path, json_encode($old->getAttributes(), JSON_THROW_ON_ERROR));
|
||||||
App\Models\SubscribeTemplate::setContent('singbox', $replacement);
|
App\Models\SubscribeTemplate::setContent('singbox', $replacement);
|
||||||
|
|||||||
@ -2,11 +2,27 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
# Credential files are installed separately with mode 0600.
|
# Credential files are installed separately with mode 0600.
|
||||||
[[ $(id -u) == 0 ]] || exit 1
|
[[ $(id -u) == 0 ]] || exit 1
|
||||||
|
listen_port=''
|
||||||
|
tls_domain=''
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
--listen-port=*) listen_port=${arg#*=} ;;
|
||||||
|
--tls-domain=*) tls_domain=${arg#*=} ;;
|
||||||
|
*) echo 'Usage: install-node.sh --listen-port=24443 --tls-domain=us01.example.com'; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
[[ $listen_port =~ ^[0-9]+$ && ${#listen_port} -le 5 ]] && (( 10#$listen_port >= 1024 && 10#$listen_port <= 65535 )) || { echo 'Explicit valid listen port required'; exit 1; }
|
||||||
|
[[ $tls_domain =~ ^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$ ]] || { echo 'Explicit TLS domain required'; exit 1; }
|
||||||
[[ -s /etc/dpl-node/config.yml && -s /etc/dpl-node/secret.env ]] || { echo 'Private node configuration missing'; exit 1; }
|
[[ -s /etc/dpl-node/config.yml && -s /etc/dpl-node/secret.env ]] || { echo 'Private node configuration missing'; exit 1; }
|
||||||
if ss -lntH '( sport = :24443 )' | grep -q .; then
|
[[ ! -e /etc/systemd/system/dpl-node.service && ! -e /opt/dpl-node/xboard-node ]] || { echo 'DPL backend already installed; use a separately reviewed Git update'; exit 1; }
|
||||||
echo 'Port 24443 already in use; inspect before deployment'; exit 1
|
if ss -lntH "( sport = :$listen_port )" | grep -q .; then
|
||||||
|
echo "Port $listen_port already in use; inspect before deployment"; exit 1
|
||||||
fi
|
fi
|
||||||
systemctl is-active --quiet XrayR
|
if systemctl list-unit-files XrayR.service --no-legend | grep -q '^XrayR.service'; then
|
||||||
|
systemctl is-active --quiet XrayR || { echo 'Existing XrayR is not active; investigate before installation'; exit 1; }
|
||||||
|
fi
|
||||||
|
printf '%s\n' "$tls_domain" > /etc/dpl-node/certificate-domain
|
||||||
|
chmod 644 /etc/dpl-node/certificate-domain
|
||||||
install -d -m 755 /opt/dpl-node
|
install -d -m 755 /opt/dpl-node
|
||||||
install -d -m 700 /var/lib/dpl-node /var/lib/dpl-node/kernel
|
install -d -m 700 /var/lib/dpl-node /var/lib/dpl-node/kernel
|
||||||
curl --fail --location --silent --show-error \
|
curl --fail --location --silent --show-error \
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -eu
|
set -eu
|
||||||
# Copy under renewal-hooks/deploy only after auditing all existing hooks.
|
# Copy under renewal-hooks/deploy only after auditing all existing hooks.
|
||||||
[ "${RENEWED_LINEAGE:-}" = /etc/letsencrypt/live/us01.deeplink-subscribe.com ] || exit 0
|
[ -s /etc/dpl-node/certificate-domain ] || exit 0
|
||||||
|
domain=$(cat /etc/dpl-node/certificate-domain)
|
||||||
|
[ "${RENEWED_LINEAGE:-}" = "/etc/letsencrypt/live/$domain" ] || exit 0
|
||||||
systemctl try-restart dpl-node
|
systemctl try-restart dpl-node
|
||||||
|
|||||||
@ -26,7 +26,6 @@
|
|||||||
{
|
{
|
||||||
"type": "https",
|
"type": "https",
|
||||||
"server": "223.5.5.5",
|
"server": "223.5.5.5",
|
||||||
"detour": "direct",
|
|
||||||
"tag": "local"
|
"tag": "local"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@ -15,7 +15,7 @@ for version in (4, 6):
|
|||||||
assert all(n.version == version and n.prefixlen >= (8 if version == 4 else 16) for n in nets), "Invalid trust range"
|
assert all(n.version == version and n.prefixlen >= (8 if version == 4 else 16) for n in nets), "Invalid trust range"
|
||||||
ranges.extend(str(n) for n in nets)
|
ranges.extend(str(n) for n in nets)
|
||||||
assert len(ranges) == len(set(ranges)), "Duplicate ranges"
|
assert len(ranges) == len(set(ranges)), "Duplicate ranges"
|
||||||
data = ("# DPL only: synchronized from Cloudflare official lists.\n" +
|
data = ("# Subscription vhosts: synchronized from Cloudflare official lists.\n" +
|
||||||
"".join(f"set_real_ip_from {n};\n" for n in ranges) +
|
"".join(f"set_real_ip_from {n};\n" for n in ranges) +
|
||||||
"real_ip_header CF-Connecting-IP;\nreal_ip_recursive off;\n").encode()
|
"real_ip_header CF-Connecting-IP;\nreal_ip_recursive off;\n").encode()
|
||||||
old = target.read_bytes() if target.exists() else None
|
old = target.read_bytes() if target.exists() else None
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import argparse
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import shutil
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
@ -55,6 +56,13 @@ with tempfile.TemporaryDirectory(prefix='dpl-client-') as d:
|
|||||||
assert trace.get('ip') == a.expected_exit, 'Second exit check mismatch'
|
assert trace.get('ip') == a.expected_exit, 'Second exit check mismatch'
|
||||||
print(json.dumps({'anytls': True, 'relay': q['host'], 'port': q['port'], 'strict_tls': True,
|
print(json.dumps({'anytls': True, 'relay': q['host'], 'port': q['port'], 'strict_tls': True,
|
||||||
'exit_ip': ip, 'country': trace.get('loc'), 'https_tls': trace.get('tls')}, ensure_ascii=False))
|
'exit_ip': ip, 'country': trace.get('loc'), 'https_tls': trace.get('tls')}, ensure_ascii=False))
|
||||||
|
except Exception:
|
||||||
|
log.flush()
|
||||||
|
failure = pathlib.Path(a.qa).parent / 'client-failure.log'
|
||||||
|
shutil.copyfile(pathlib.Path(d) / 'client.log', failure)
|
||||||
|
failure.chmod(0o600)
|
||||||
|
print(f'Client failed; protected diagnostic log: {failure}')
|
||||||
|
raise
|
||||||
finally:
|
finally:
|
||||||
proc.terminate()
|
proc.terminate()
|
||||||
try:
|
try:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user