mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-10-28 08:20:49 +08:00
将扩展配置、接口和设置页切换为 EasyFrp,支持按行填写多个客户端连接 URL,通过 easyfrpc control 启动并校验协议与密钥路径。 旧 gostc 配置不自动启用 EasyFrp,升级后需重新配置;启动日志不再输出命令参数,避免暴露连接信息。 完整 Docker 镜像包含 easyfrpc、easytier-core、easytier-cli 和 frpc,通过独立下载脚本及版本锁定文件校验下载摘要和二进制架构。
69 lines
3.3 KiB
Python
69 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Fetch the pinned EasyFrp, EasyTier and frp clients for full Docker images."""
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import os
|
|
from pathlib import Path, PurePosixPath
|
|
import shutil
|
|
import struct
|
|
import tarfile
|
|
import tempfile
|
|
import urllib.request
|
|
import zipfile
|
|
|
|
|
|
def install(platform, output):
|
|
architecture = {'linux/amd64': 'x86_64', 'linux/arm64': 'aarch64',
|
|
'linux/arm/v7': 'arm'}[platform]
|
|
lock = json.loads(Path(__file__).with_name('remote-access.lock.json').read_text())
|
|
output.mkdir(parents=True, exist_ok=True)
|
|
expected = {'arm': (1, 40), 'aarch64': (2, 183), 'x86_64': (2, 62)}[architecture]
|
|
opener = urllib.request.build_opener(
|
|
urllib.request.ProxyHandler({'http': os.environ['CURL_PROXY'], 'https': os.environ['CURL_PROXY']})
|
|
) if os.environ.get('CURL_PROXY') else urllib.request.build_opener()
|
|
# Validate the entire download before replacing any staged executable.
|
|
with tempfile.TemporaryDirectory(prefix='one-kvm-remote-tools-') as temporary:
|
|
staging = Path(temporary)
|
|
for spec in lock['tools'].values():
|
|
asset = spec['assets'][architecture]
|
|
archive = staging / asset['archive']
|
|
prefix = os.environ.get('GHPROXY_PREFIX', '').rstrip('/')
|
|
url = prefix + '/' + asset['url'] if prefix else asset['url']
|
|
with opener.open(url, timeout=120) as response:
|
|
with archive.open('wb') as stream:
|
|
shutil.copyfileobj(response, stream)
|
|
if hashlib.sha256(archive.read_bytes()).hexdigest() != asset['sha256']:
|
|
raise ValueError('release checksum differs: ' + archive.name)
|
|
for name in spec['binaries']:
|
|
if zipfile.is_zipfile(archive):
|
|
with zipfile.ZipFile(archive) as source:
|
|
matches = [item for item in source.infolist()
|
|
if not item.is_dir() and PurePosixPath(item.filename).name == name]
|
|
if len(matches) != 1:
|
|
raise ValueError('expected one executable: ' + name)
|
|
data = source.read(matches[0])
|
|
else:
|
|
with tarfile.open(archive, 'r:gz') as source:
|
|
matches = [item for item in source if item.isfile() and PurePosixPath(item.name).name == name]
|
|
if len(matches) != 1:
|
|
raise ValueError('expected one executable: ' + name)
|
|
data = source.extractfile(matches[0]).read()
|
|
if (data[:4] != b'\x7fELF' or data[5] != 1
|
|
or (data[4], struct.unpack('<H', data[18:20])[0]) != expected):
|
|
raise ValueError('executable architecture differs: ' + name)
|
|
path = staging / name
|
|
path.write_bytes(data)
|
|
path.chmod(0o755)
|
|
for spec in lock['tools'].values():
|
|
for name in spec['binaries']:
|
|
shutil.copy2(staging / name, output / name)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument('--platform', required=True, choices=('linux/amd64', 'linux/arm64', 'linux/arm/v7'))
|
|
parser.add_argument('--output', required=True, type=Path)
|
|
args = parser.parse_args()
|
|
install(args.platform, args.output)
|