免备案VPS 最适合被低估的用途,不是扛站,是当隔离沙盒:跑爬虫联调、Webhook 模拟、第三方 SDK 联调、AI 工具外调、多分支预览。
问题是“裸机直接装”会把机器搞成垃圾场,还容易把 3306/6379 漏公网。本文用 Linux 网络命名空间 + Docker 内部网络,搭一套:服务只监听内网、端口不暴露公网、数据库走 SSH 隧道、环境随删随建、数据全脱敏的沙盒闭环。
一、沙盒设计原则:先定“不做什么”
- 不存生产库(哪怕脱敏也单独实例)
- 不绑 0.0.0.0 裸开(数据库/Redis/Adminer 全走 127.0.0.1)
- 不写真实密钥(用 fake env / Vault 本地版 / 占位 token)
- 不长期运行(PR 合入即销毁)
- 公网只进 80/443(反代),管理面只进 SSH 隧道
- kkce ping检测中看看延迟高低
目标:一台境外小机 = 多个互相看不见的临时实验室。
二、宿主机基线:先锁门再进沙盒
bash
# 非 root 用户 + 密钥 adduser sandbox usermod -aG sudo sandbox # 改 SSH 端口、禁密码 # /etc/ssh/sshd_config: Port 22222 / PermitRootLogin no / PasswordAuthentication no # 防火墙:只开反代口 ufw default deny incoming ufw allow 22222/tcp ufw allow 80/tcp ufw allow 443/tcp ufw enable # 内核转发(Docker 要用) sysctl -w net.ipv4.ip_forward=1
三、用 Network Namespace 做“硬隔离”(不只用 Docker)
Docker 网络是软隔离,Namespace 是内核级隔离。测试不可信代码时更有用。
bash
# 建一个沙盒网络命名空间 ip netns add sandbox-a # 建 veth 对 ip link add veth-a type veth peer name veth-a-br # 把一端塞进 namespace ip link set veth-a netns sandbox-a # 宿主机端挂桥 ip link set veth-a-br up ip addr add 10.10.10.1/24 dev veth-a-br # namespace 内配 IP ip netns exec sandbox-a ip addr add 10.10.10.2/24 dev veth-a ip netns exec sandbox-a ip link set lo up ip netns exec sandbox-a ip link set veth-a up ip netns exec sandbox-a ip route add default via 10.10.10.1
在 namespace 里跑服务,宿主机外网根本摸不到它:
bash
ip netns exec sandbox-a python3 -m http.server 8080
出网策略(只允许 53/80/443 出,禁 ICMP 出、禁内网扫):
bash
ip netns exec sandbox-a iptables -A OUTPUT -o lo -j ACCEPT ip netns exec sandbox-a iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT ip netns exec sandbox-a iptables -A OUTPUT -p udp --dport 53 -j ACCEPT ip netns exec sandbox-a iptables -A OUTPUT -p tcp -m multiport --dports 80,443 -j ACCEPT ip netns exec sandbox-a iptables -P OUTPUT DROP
效果:沙盒能调外网 API,但不能扫内网、不能裸连宿主机。
四、Docker 层:数据库/Redis 全绑 127.0.0.1
docker-compose.sandbox.yml:
yaml
services: app: build: . networks: [internal] expose: - "3000" db: image: postgres:16-alpine environment: POSTGRES_PASSWORD: devonly networks: [internal] # 不写 ports,外网不可见 redis: image: redis:7-alpine networks: [internal] proxy: image: nginx:alpine depends_on: [app] ports: - "127.0.0.1:8080:80" # 只绑本地 networks: [internal, front] networks: internal: front: driver: bridge
启动后:
- 数据库只在
internal网络,宿主机外网连不到 - 本地调试用 SSH 隧道:
bash
ssh -L 5432:localhost:5432 -L 8080:localhost:8080 sandbox@免备案VPS_IP
笔记本连 localhost:5432 就像库在本地。
五、反代只收 CDN,源站不裸暴露
Nginx(宿主机或 proxy 容器):
nginx
server { listen 80; server_name preview.example.com; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
防火墙层再收一道(DOCKER-USER 链,别只信 ufw):
bash
iptables -I DOCKER-USER -i eth0 ! -s CDN回源段 -p tcp --dport 8080 -j DROP
六、数据:沙盒里只放“假数据”
脱敏脚本示例(生产导出前先跑):
sql
-- 假数据生成,不碰真 PII INSERT INTO users (id, phone_hash, email_mask, city) SELECT gen_random_uuid(), md5('fake_'||g::text), 'user'||g||'@example.com', (ARRAY['HK','SG','TK','SJ'])[g%4+1];
规则:
- 手机号/身份证:哈希或删除
- 邮箱:掩码
- 地址:只留城市级
- 支付/人脸:沙盒库里根本不存在这些字段
合规底线(参考个人信息出境要求):
- 出境前完成数据分类分级与影响评估
- 最小字段、脱敏、可审计
- 不把境外沙盒当“生产备份盘”
七、资源限流:别让沙盒把机器吃崩
yaml
deploy: resources: limits: memory: 512M cpus: "1.0"
或运行时:
bash
docker run -d --memory=512m --cpus=1 --pids-limit=200 sandbox-img
再加健康检查:
bash
curl -fsS http://127.0.0.1:8080/health || docker compose restart
八、生命周期:CI 触发,自动回收
GitHub Actions 思路:
yaml
preview: on: pull_request steps: - ssh sandbox@vps "TAG=$PR docker compose -f dc.sandbox.yml up -d" - curl 拨测 preview 域名 after-merge: - ssh sandbox@vps "docker compose -f dc.sandbox.yml down -v"
命名规范:
sandbox-pr-123网络隔离- 合并即
down -v清卷 - 每日凌晨扫残留容器,超 24h 自动删
九、可观测:轻量三件事
bash
# 1. 命名空间/容器存活 ip netns list docker ps --format '{{.Names}}\t{{.Status}}' # 2. 端口暴露审计(防误绑公网) ss -lntp | grep -E ':3306|:6379|:5432' && echo "WARN 公网裸库" # 3. 外网可达拨测 curl -w "ttfb=%{time_starttransfer}\n" https://preview.example.com/health
告警:
- 发现 DB 端口绑 0.0.0.0 → 立即重启隔离
- 沙盒 CPU 持续 >90% 10min → 缩容/销毁
- 证书 <7 天 → 自动续
十、什么不该放免备案沙盒
- 大陆用户真实订单/支付流水
- 未脱敏人脸、身份证、病历
- 生产 .env、真实云密钥
- 长期不销毁的“临时”服务
这些不是技术不行,是合规和习惯问题。
十一、总结
免备案VPS 用成沙盒的正确姿势:
Namespace 做内核隔离,Docker 内部网做服务隔离,SSH 隧道做运维入口,脱敏数据做唯一数据源。
它不该是“省备案的正式机”,而该是:
- 不可信代码的防爆间
- 多分支预览的临时场
- 外调 API 的隔离出口
- 出事即删、不污染宿主的实验室
开发效率和安全,不一定二选一——只要网络边界画清楚。