WG认证WEB留档

koaker 发布于 8 天前 所有文章


🛠️ 第一阶段:PVE 环境准备 (基础地基)

1. 下载模板

  • PVE 界面 -> local 存储 -> CT 模板 -> 模板 -> 搜索并下载 debian-12-standard

2. 创建 LXC 容器

  • 主机名vpn-portal
  • 资源:1-2 核 CPU,512MB-1GB 内存,8GB 硬盘。
  • 网络:选择桥接 LAN 的网桥(通常是 vmbr0),IPv4 设为静态(如 192.168.123.220/24),网关填 OpenWrt IP(如 192.168.123.1)。
  • 取消勾选:“无特权容器” (Unprivileged) 建议保持勾选(为了安全),但我们需要在后面手动开启权限。

3. 修正 LXC 权限 (关键步骤,解决 Docker 报错)

  • 不要启动容器。
  • 点击容器 -> 选项 (Options) -> 功能 (Features) -> 勾选 Nestingkeyctl
  • 开启 TUN 权限与 Docker 补丁
    在 PVE 的 Shell (宿主机终端) 中执行(假设容器 ID 是 100):
    vim /etc/pve/lxc/100.conf
    在文件末尾添加以下三行:
    lxc.cgroup2.devices.allow: c 10:200 rwm
    lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
    lxc.apparmor.profile: unconfined

    (保存:Ctrl+X -> Y -> 回车)

🚀 第二阶段:系统环境初始化

启动 Debian 容器,进入控制台(Console),用 root 登录。

1. 安装基础软件 & Docker

apt update && apt install -y curl vim git openssl apache2-utils tcpdump
curl -fsSL https://get.docker.com | bash

2. 创建工作目录

mkdir -p /root/vpn-portal/public
mkdir -p /root/vpn-portal/nginx-conf
mkdir -p /root/vpn-portal/certs
mkdir -p /root/vpn-portal/wg-easy-data
cd /root/vpn-portal

🔐 第三阶段:证书与密码 (安全核心)

1. 生成自签名 HTTPS 证书

openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
  -keyout certs/selfsigned.key \
  -out certs/selfsigned.crt \
  -subj "/C=CN/ST=Shanghai/L=Shanghai/O=MyVPN/OU=IT/CN=vpn.local"

2. 设置“门户网页”的第一道密码锁

# 将 'admin' 替换为你想要的用户名,回车后输入两遍密码
htpasswd -c nginx.htpasswd admin

3. 生成 WireGuard 管理后台的密码 Hash

  • WireGuard 后台现在强制要求 Hash 密码。请运行以下命令(将 你的密码 替换为真实密码):
    bash docker run --rm --entrypoint node ghcr.io/wg-easy/wg-easy -e "console.log(require('bcryptjs').hashSync(process.argv[1], 12));" "你的密码"
  • ⚠️ 重要:复制输出的以 $ 开头的字符串。在后续配置文件中,必须将所有的 $ 替换为 $$

📦 第四阶段:配置文件编写 (业务逻辑)

确保仍在 /root/vpn-portal 目录下。

1. 下载客户端并生成网页 (index.html)

# 下载安装包
wget -O public/wireguard-installer.exe https://download.wireguard.com/windows-client/wireguard-installer.exe
wget -O public/wireguard-android.apk https://download.wireguard.com/android-client/wireguard-latest.apk

# 生成网页 (自动跳转到高位端口 28444)
cat <<EOF > public/index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>安全接入门户</title>
    <style>
        body { font-family: sans-serif; text-align: center; padding: 40px 20px; background-color: #f0f2f5; }
        .box { max-width: 500px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; box-shadow: 0 4px 10px rgba(0,0,0,0.1); }
        .btn { display: block; width: 100%; padding: 12px; margin: 10px 0; color: white; text-decoration: none; border-radius: 5px; }
        .win { background: #0078d4; }
        .and { background: #3ddc84; color: #004d1d; }
        .ios { background: #000; }
        .admin { background: #6c757d; margin-top: 20px; }
    </style>
    <script>
        function gotoAdmin() {
            var currentHost = window.location.hostname;
            // ⚠️ 如果你更改了 OpenWrt 的转发端口,请修改这里的 28444
            window.location.href = "https://" + currentHost + ":28444";
        }
    </script>
</head>
<body>
    <div class="box">
        <h1>🔒 私有网络门户</h1>
        <a href="wireguard-installer.exe" class="btn win">💻 Windows 客户端</a>
        <a href="wireguard-android.apk" class="btn and">🤖 Android 客户端</a>
        <a href="https://apps.apple.com/cn/app/wireguard/id1441195209" target="_blank" class="btn ios">🍏 iOS (App Store)</a>
        <hr>
        <a href="javascript:gotoAdmin()" class="btn admin">⚙️ 进入管理后台 (获取配置)</a>
    </div>
</body>
</html>
EOF

2. 配置 Nginx (default.conf)

cat <<EOF > nginx-conf/default.conf
server {
    listen 443 ssl;
    server_name localhost;
    ssl_certificate /etc/nginx/certs/selfsigned.crt;
    ssl_certificate_key /etc/nginx/certs/selfsigned.key;
    auth_basic "Restricted Portal";
    auth_basic_user_file /etc/nginx/.htpasswd;
    root /usr/share/nginx/html;
    index index.html;
    location / { try_files \$uri \$uri/ =404; }
}
server {
    listen 51821 ssl;
    server_name localhost;
    ssl_certificate /etc/nginx/certs/selfsigned.crt;
    ssl_certificate_key /etc/nginx/certs/selfsigned.key;
    location / {
        proxy_pass http://wg-easy:51821;
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host \$host;
        proxy_set_header X-Forwarded-Proto https;
    }
}
EOF

3. 配置 Docker Compose (docker-compose.yml)

  • 请修改 WG_HOST 为你的域名。
  • 请修改 PASSWORD_HASH (记得用 $$ 转义)。
cat <<EOF > docker-compose.yml
services:
  wg-easy:
    image: ghcr.io/wg-easy/wg-easy
    container_name: wg-easy
    environment:
      - WG_HOST=你的公网域名
      # ⚠️ 外部高位端口,告诉客户端连接这个端口
      - WG_PORT=28520
      # ⚠️ 密码 Hash,注意 $ 要写成 $$
      - PASSWORD_HASH=$$2b$$12$$这里填你生成的HASH字符串
      - WG_DEFAULT_ADDRESS=10.8.0.x
      - WG_DEFAULT_DNS=114.114.114.114
      - WG_ALLOWED_IPS=0.0.0.0/0
      - WG_MTU=1280
    volumes:
      - ./wg-easy-data:/etc/wireguard
    ports:
      # ⚠️ 核心映射:宿主机 51820 -> 容器 28520
      - "28520:28520/udp"
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
      - SYS_MODULE

  portal:
    image: nginx:alpine
    container_name: vpn-portal
    volumes:
      - ./public:/usr/share/nginx/html
      - ./nginx-conf/default.conf:/etc/nginx/conf.d/default.conf
      - ./nginx.htpasswd:/etc/nginx/.htpasswd
      - ./certs:/etc/nginx/certs
    ports:
      - "443:443"
      - "28444:51821"
    restart: unless-stopped
    depends_on:
      - wg-easy
EOF

4. 启动服务

docker compose up -d

🌐 第五阶段:OpenWrt 端口转发 (连接桥梁)

假设 Debian 容器 IP 为 192.168.123.220。请在 OpenWrt 设置以下 3 条转发规则:

描述协议外部端口 (WAN)内部 IP (LAN)内部端口备注
门户网页TCP28443192.168.123.220443浏览器访问入口
管理后台TCP28444192.168.123.22028444JS脚本自动跳转的目标
VPN数据UDP28520192.168.123.22028520必须仅限 UDP

📱 第六阶段:最终使用指南

1. 用户访问流程

  • 浏览器打开 https://你的域名:28443
  • 接受自签证书警告(点击“高级” -> “继续”)。
  • 验证 1:输入 Nginx 账号密码。
  • 下载对应客户端安装。
  • 点击“进入管理后台”。

2. 获取配置流程

  • 浏览器会自动跳转到 https://你的域名:28444
  • 接受自签证书警告。
  • 验证 2:输入 WireGuard 后台密码。
  • 点击 New Client,输入名称,点击 Create。
  • 手机端:打开 App 扫描二维码。
  • 电脑端:下载 .conf 文件导入。

3. 关键测试

  • 务必关闭 Wi-Fi,使用手机 5G 网络点击连接。
  • 看到数据传输 (Rx/Tx) 跳动,即为大功告成!
此作者没有提供个人介绍。
最后更新于 2025-12-31