无公网IP情况下家庭wireguard服务器的搭建
### 方案概述1. **家庭网络环境**:
- 家庭宽带使用内网IP(通常是100.64.0.0/10)。
- 运营商分配的公网IPv6地址。
- 使用NAT1进行UDP打洞,获取公网IPv4地址和端口。
2. **服务器配置**:
- 在公网VPS上搭建一个键值对服务器(例如使用PHP编写)。
- 在家庭网络中运行WireGuard服务器,监听特定端口。
3. **客户端配置**:
- 客户端在有IPv6的情况下直接使用IPv6连接WireGuard服务器。
- 客户端在没有IPv6的情况下,通过键值对服务器查询WireGuard服务器的公网IPv4和端口。
- 定义计划任务,定期更新WireGuard服务器的endpoint。
### 详细步骤
#### 1. 公网VPS上的键值对服务器
- **编写键值对服务器**:
- 使用PHP或其他语言编写一个简单的键值对服务器,用于存储和查询WireGuard服务器的公网IPv4和端口信息。
- 服务器可以提供API接口,如 `GET ?id=xxx` 和 `POST ?id=xxx&value=xxx`。
- **键值对服务器示例代码**(PHP):
<?php // 设置数据库文件路径 $dbFile = __DIR__ . '/data.db'; // 创建一个新的PDO实例连接到SQLite数据库 try { $pdo = new PDO("sqlite:$dbFile"); // 设置错误模式为异常 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 创建表(如果不存在) $pdo->exec(" CREATE TABLE IF NOT EXISTS key_value_store ( id TEXT PRIMARY KEY, value TEXT ) "); } catch (PDOException $e) { die("数据库连接失败: " . $e->getMessage()); } // 检查请求方法 if ($_SERVER['REQUEST_METHOD'] === 'POST') { // 处理POST请求,保存键值对 $id = isset($_POST['id']) ? $_POST['id'] : null; $value = isset($_POST['value']) ? $_POST['value'] : null; if ($id && $value) { try { // 插入或更新数据 $stmt = $pdo->prepare('INSERT OR REPLACE INTO key_value_store (id, value) VALUES (:id, :value)'); $stmt->execute([':id' => $id, ':value' => $value]); echo "键值对 {$id}={$value} 已保存"; } catch (PDOException $e) { echo "数据库操作失败: " . $e->getMessage(); } } else { echo "缺少必要的参数:id 和 value"; } } elseif ($_SERVER['REQUEST_METHOD'] === 'GET') { // 处理GET请求,查询键值对 $id = isset($_GET['id']) ? $_GET['id'] : null; if ($id) { try { $stmt = $pdo->prepare('SELECT value FROM key_value_store WHERE id = :id'); $stmt->execute([':id' => $id]); $result = $stmt->fetch(PDO::FETCH_ASSOC); if ($result) { echo $result['value']; } else { echo "未找到ID {$id}"; } } catch (PDOException $e) { echo "数据库操作失败: " . $e->getMessage(); } } else { echo "缺少必要的参数:id"; } } else { // 不支持的方法 http_response_code(405); echo "不支持的请求方法"; } ?>
#### 2. 家庭网络中的WireGuard服务器
- **安装和配置WireGuard**:
- 在家庭网络中安装并配置WireGuard服务器。
- 配置WireGuard服务器监听特定端口(例如51820)。
- **使用NAT映射工具**:
- 使用NAT映射工具natpmp来获取公网IPv4地址和端口。
- 将公网IPv4地址和端口更新到键值对服务器。
- **更新natmap获取的ip与端口示例脚本**(Shell):
#!/bin/sh curl -X POST https://服务器域名/键值对文件名.php -d "id=自定义&value=${1}:${2}"
#### 3. 客户端配置
- **配置WireGuard客户端**:
- 配置WireGuard客户端,使其优先使用IPv6连接。
- 如果客户端没有IPv6,则从键值对服务器获取WireGuard服务器的公网IPv4和端口。
- **示例客户端配置文件**:
```ini
[Interface]
PrivateKey = <Your-PrivateKey>
Address = 10.0.0.2/24
DNS = 1.1.1.1, 8.8.8.8
[Peer]
PublicKey = <Server-Public-Key>
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = <Server-IPv6-Address>:51820
PersistentKeepalive = 25
```
- **动态更新Endpoint**:
- 编写一个脚本,当网络连通时或每半小时定时更新WireGuard服务器的endpoint。
- 使用计划任务来运行这个脚本。
- **示例脚本**(VBS):
Set WshShell = CreateObject("WScript.Shell") WshShell.Run "powershell -WindowStyle Hidden -Command ""& { wg set wg接口名 peer 服务器公钥 endpoint (Invoke-WebRequest -Uri https://服务器域名/键值对文件名.php?id=自定义).Content }""", 0, True Set WshShell = Nothing
- **创建计划任务**:
- 打开“任务计划程序”。
- 创建一个新的基本任务或触发器。
- 在“常规”选项卡中,输入任务名称和描述。
- 在“触发器”部分,设置任务的触发条件为发生事件时,选择自定义,输入如下 xml。
<QueryList> <Query Id="0" Path="Microsoft-Windows-NCSI/Operational"> <Select Path="Microsoft-Windows-NCSI/Operational">*[System[(EventID=4042)]] and *[EventData[Data[@Name='Capability']='2']]</Select> </Query> </QueryList>
- 在“触发器”部分,设置任务的触发条件每半小时。
- 在“操作”部分,选择“启动程序”。- 在“程序/脚本”字段中,输入 `你的vbs脚本全路径`。
- 确保在“常规”选项卡中选择了“使用最高权限运行”。
通过上述步骤,您可以实现一个灵活的家庭WireGuard服务器配置,支持IPv4和IPv6连接,并能够自动更新服务器的endpoint。这样,无论客户端是否有IPv6,都能可靠地连接到WireGuard服务器。
标签: wireguard
发表评论: