Files
nas/scripts/setup-frp-on-nas.sh
T

192 lines
5.6 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# 在 NAS 上执行(由 setup-frp-remote.sh 上传并调用,也可手动跑):
# ① 写 frpc 配置 + docker compose 拉起(需 sudo,会提示输 DSM 密码)
# ② mihomo 加 hosts 覆盖 / fake-ip-filter / use-hosts(幂等,自动备份,热重载)
# ③ 端到端验证
# 前提:/tmp/frp-setup/token 里是 frp auth token(由远端脚本从 Bitwarden 送来)。
set -euo pipefail
FRP_DIR=/volume1/docker/frp
CFG=/volume1/docker/proxy/mihomo/config.yaml
TOKEN_FILE=/tmp/frp-setup/token
[ -s "$TOKEN_FILE" ] || { echo "!! 缺 token 文件 $TOKEN_FILE(应由 setup-frp-remote.sh 生成)"; exit 1; }
read -r TOKEN < "$TOKEN_FILE"
echo "==> 1/6 写 frpc.toml + docker-compose.ymlsudo"
sudo mkdir -p "$FRP_DIR"
sudo tee "$FRP_DIR/frpc.toml" > /dev/null <<EOF
serverAddr = "103.119.13.48"
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"
sudo tee "$FRP_DIR/docker-compose.yml" > /dev/null <<'EOF'
services:
frpc:
image: snowdreamtech/frpc:0.70.0
container_name: frpc
network_mode: host
restart: unless-stopped
volumes:
- ./frpc.toml:/etc/frp/frpc.toml:ro
EOF
echo "==> 2/6 拉起 frpc 容器"
# DSM 的 docker 在 /usr/local/binContainer Manager 符号链接),不在 sudo 的 secure_path 里,必须绝对路径
DOCKER=/usr/local/bin/docker
COMPOSE=/usr/local/bin/docker-compose
cd "$FRP_DIR"
if sudo "$COMPOSE" version >/dev/null 2>&1; then
sudo "$COMPOSE" up -d
else
sudo "$DOCKER" compose up -d
fi
echo "==> 3/6 mihomohosts 覆盖 + fake-ip-filter + use-hosts(幂等)"
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: truemihomo 默认 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
echo "==> 6/6 验证 frpc 隧道"
sleep 2
sudo /usr/local/bin/docker logs frpc --tail 20 2>&1 || true
rm -f "$TOKEN_FILE"
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 失败:对应本地端口没起。"