204 lines
6.2 KiB
Bash
Executable File
204 lines
6.2 KiB
Bash
Executable File
#!/bin/bash
|
||
# 在 NAS 上执行(由 setup-frp-remote.sh 上传并调用,也可手动跑):
|
||
# ① 写 frpc 配置 + 安装 frpc 二进制 + systemd 常驻(需 sudo,会提示输 DSM 密码)
|
||
# (不用 docker:NAS 出国通道不通拉不了 Docker Hub 镜像;二进制由远端脚本推来)
|
||
# ② mihomo 加 hosts 覆盖 / fake-ip-filter / use-hosts(幂等,自动备份,热重载)
|
||
# ③ 端到端验证
|
||
# 前提:/tmp/frp-setup/ 下有 token(Bitwarden 取来)和 frpc(linux_amd64 二进制)。
|
||
set -euo pipefail
|
||
|
||
FRP_DIR=/volume1/docker/frp
|
||
CFG=/volume1/docker/proxy/mihomo/config.yaml
|
||
TOKEN_FILE=/tmp/frp-setup/token
|
||
FRPC_BIN=/tmp/frp-setup/frpc
|
||
|
||
[ -s "$TOKEN_FILE" ] || { echo "!! 缺 token 文件 $TOKEN_FILE(应由 setup-frp-remote.sh 生成)"; exit 1; }
|
||
[ -s "$FRPC_BIN" ] || { echo "!! 缺 frpc 二进制 $FRPC_BIN(应由 setup-frp-remote.sh 上传)"; exit 1; }
|
||
read -r TOKEN < "$TOKEN_FILE"
|
||
|
||
echo "==> 1/6 写 frpc.toml + docker-compose.yml(sudo)"
|
||
sudo mkdir -p "$FRP_DIR"
|
||
sudo tee "$FRP_DIR/frpc.toml" > /dev/null <<EOF
|
||
serverAddr = "182.92.213.171"
|
||
serverPort = 7000
|
||
auth.method = "token"
|
||
auth.token = "$TOKEN"
|
||
transport.tls.enable = true
|
||
|
||
[[proxies]]
|
||
name = "git-ssh"
|
||
type = "tcp"
|
||
localIP = "127.0.0.1"
|
||
localPort = 2222
|
||
remotePort = 2222
|
||
|
||
[[proxies]]
|
||
name = "git-web"
|
||
type = "tcp"
|
||
localIP = "127.0.0.1"
|
||
localPort = 3000
|
||
remotePort = 3000
|
||
|
||
[[proxies]]
|
||
name = "dsm"
|
||
type = "tcp"
|
||
localIP = "127.0.0.1"
|
||
localPort = 5001
|
||
remotePort = 5001
|
||
|
||
[[proxies]]
|
||
name = "nas-ssh"
|
||
type = "tcp"
|
||
localIP = "127.0.0.1"
|
||
localPort = 22
|
||
remotePort = 10022
|
||
|
||
[[proxies]]
|
||
name = "win-rdp"
|
||
type = "tcp"
|
||
localIP = "192.168.3.88"
|
||
localPort = 3389
|
||
remotePort = 3389
|
||
|
||
[[proxies]]
|
||
name = "win-ssh"
|
||
type = "tcp"
|
||
localIP = "192.168.3.88"
|
||
localPort = 22
|
||
remotePort = 10023
|
||
EOF
|
||
sudo chmod 600 "$FRP_DIR/frpc.toml"
|
||
|
||
echo "==> 2/6 安装 frpc 二进制 + systemd 常驻"
|
||
sudo install -m 755 "$FRPC_BIN" /usr/local/bin/frpc
|
||
sudo tee /etc/systemd/system/frpc.service > /dev/null <<'EOF'
|
||
[Unit]
|
||
Description=frp client (home reverse tunnel to ali frps)
|
||
After=network-online.target
|
||
Wants=network-online.target
|
||
|
||
[Service]
|
||
ExecStart=/usr/local/bin/frpc -c /volume1/docker/frp/frpc.toml
|
||
Restart=always
|
||
RestartSec=5
|
||
LimitNOFILE=65536
|
||
MemoryLimit=64M
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
sudo systemctl daemon-reload
|
||
sudo systemctl enable frpc >/dev/null 2>&1 || true
|
||
sudo systemctl restart frpc
|
||
|
||
echo "==> 3/6 mihomo:hosts 覆盖 + fake-ip-filter + use-hosts(幂等)"
|
||
if [ ! -f "$CFG" ]; then
|
||
echo " !! mihomo 配置不存在($CFG)——NAS 上 mihomo 已不在运行,跳过 3/4/5 步。"
|
||
echo " !! 家内 DNS 覆盖需另行方案(群晖 DNS Server 套件),见 docs/remote-access-frp.html。"
|
||
SKIP_MIHOMO=1
|
||
fi
|
||
if [ -z "${SKIP_MIHOMO:-}" ]; then
|
||
cp "$CFG" "$CFG.bak.frp"
|
||
echo " 备份: $CFG.bak.frp"
|
||
python3 - "$CFG" <<'PY'
|
||
import re, sys
|
||
|
||
p = sys.argv[1]
|
||
text = open(p).read()
|
||
orig = text
|
||
|
||
HOSTS = {
|
||
"nas.yanmeiai.com": "192.168.3.200",
|
||
"git.yanmeiai.com": "192.168.3.200",
|
||
"win.yanmeiai.com": "192.168.3.88",
|
||
"git.51yanmei.com": "192.168.3.200", # 兼容既有 git remote
|
||
}
|
||
|
||
lines = text.splitlines(True)
|
||
|
||
# ---- ① fake-ip-filter 追加域名(防 fake-ip 吞掉 hosts 真实值)----
|
||
missing = [d for d in HOSTS if ("'" + d + "'") not in text and ('"' + d + '"') not in text and ("- " + d) not in text]
|
||
out = []
|
||
inserted_filter = False
|
||
for i, ln in enumerate(lines):
|
||
out.append(ln)
|
||
if (not inserted_filter) and re.match(r"\s*fake-ip-filter:\s*$", ln):
|
||
# 探测下一行列表项缩进
|
||
indent = " "
|
||
for nxt in lines[i+1:]:
|
||
m = re.match(r"(\s*)- ", nxt)
|
||
if m:
|
||
indent = m.group(1)
|
||
break
|
||
for d in missing:
|
||
out.append(indent + "- '" + d + "'\n")
|
||
inserted_filter = True
|
||
if missing and not inserted_filter:
|
||
print(" !! 没找到 fake-ip-filter: 段,请人工检查", file=sys.stderr)
|
||
sys.exit(1)
|
||
lines = out
|
||
|
||
# ---- ② hosts 段(家内答案:域名 → 内网 IP)----
|
||
text = "".join(lines)
|
||
have_hosts = re.search(r"^hosts:\s*$", text, re.M)
|
||
need = {d: ip for d, ip in HOSTS.items() if not re.search(r"^\s+" + re.escape(d) + ":", text, re.M)}
|
||
if need:
|
||
if have_hosts:
|
||
out = []
|
||
done = False
|
||
for ln in text.splitlines(True):
|
||
out.append(ln)
|
||
if (not done) and re.match(r"^hosts:\s*$", ln):
|
||
for d, ip in need.items():
|
||
out.append(" " + d + ": " + ip + "\n")
|
||
done = True
|
||
text = "".join(out)
|
||
else:
|
||
block = "\nhosts:\n"
|
||
for d, ip in need.items():
|
||
block += " " + d + ": " + ip + "\n"
|
||
text += block
|
||
|
||
# ---- ③ dns.use-hosts: true(mihomo 默认 false,不开 hosts 对 DNS 响应不生效)----
|
||
if re.search(r"^\s*use-hosts:", text, re.M):
|
||
text = re.sub(r"(^\s*use-hosts:\s*)false", r"\1true", text, flags=re.M)
|
||
else:
|
||
out = []
|
||
done = False
|
||
for ln in text.splitlines(True):
|
||
out.append(ln)
|
||
if (not done) and re.match(r"^dns:\s*$", ln):
|
||
out.append(" use-hosts: true\n")
|
||
done = True
|
||
if not done:
|
||
print(" !! 没找到 dns: 段,请人工检查", file=sys.stderr)
|
||
sys.exit(1)
|
||
text = "".join(out)
|
||
|
||
if text != orig:
|
||
open(p, "w").write(text)
|
||
print(" 已写入(hosts %d 条新增 / fake-ip-filter %d 条新增)" % (len(need), len(missing)))
|
||
else:
|
||
print(" 无需改动(已是目标状态)")
|
||
PY
|
||
|
||
echo "==> 4/6 热重载 mihomo"
|
||
curl -s -X PUT 'http://127.0.0.1:9090/configs?force=true' \
|
||
-H 'Content-Type: application/json' \
|
||
-d '{"path":"/root/.config/mihomo/config.yaml"}'
|
||
echo " reload 已请求"
|
||
|
||
echo "==> 5/6 验证家内解析(期望 192.168.3.200)"
|
||
sleep 1
|
||
nslookup git.yanmeiai.com 127.0.0.1 2>&1 | tail -3
|
||
fi # SKIP_MIHOMO
|
||
|
||
echo "==> 6/6 验证 frpc 隧道"
|
||
sleep 3
|
||
sudo systemctl is-active frpc
|
||
sudo journalctl -u frpc --no-pager -n 20 2>/dev/null || sudo systemctl status frpc --no-pager | tail -20
|
||
rm -f "$TOKEN_FILE" "$FRPC_BIN"
|
||
echo ""
|
||
echo "完成。检查上方日志:应有 'login to server success',且 git-ssh/git-web/dsm/nas-ssh/win-rdp/win-ssh 六个 proxy 'start proxy success'。"
|
||
echo "若 login 失败:token 不对或 pangolin1:7000 不通;若个别 proxy 失败:对应本地端口没起。"
|