松哥的笔记
无公网IP情况下家庭wireguard服务器的搭建
2024-10-30 lqy
### 方案概述



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服务器。
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容