一 场景描述
在上篇文章《强大的chatgpt–利用动态域名编写可自动更新frpc的脚本实现内网穿透》中,利用公网VPS,结合动态域名可以实现内网机器 的穿透,该方案简单实用,无需额外配置,但该方案有一个缺点,就是当FRPS端的公网IP变化时,动态域名更新解析需要一定的时间,时间长短与所用的网络环境有关,比如本人的联通公网宽带,可以成功访问动态域名的时间大约五至十分钟,但移动网络则达半小时以上,如果在动态域名更新的这段时间内,是无法访问内网机器的,当时如果动态IP更新在半夜或我们一般不常访问内网机器, 这种影响也可以忽略,但对于经常访问且要保证联通时效的情况下,上篇方案就不合适了。本方案解决以上问题所在。
二 准备条件
1..自带公网的家宽一条,内网宽带多条。
2.连接公网端的设备完成安装frps,推荐使用openwrt,自带frps服务,注意不是frp穿透,是服务端。
3.chatgtp账号一个,用于生成代码。
4.固定国外VPS一个,用于记录公网端动态IP更新的数据。
5.可选域名,可用可不用。
三 实现原理
利用VPS上搭建一个php脚本,获取公网端的IP地址,公网端机器安装脚本,定期更新IP地址上传至VPS,要穿透的机器安装脚本自动访问服务器上的IP记录,当发现IP变更时,修改FRPC的配置文件并自动重启,保持FRPC配置文件里的服务器地址与动态IP一致,实现时时同步。
可有有人会说:既然有了VPS,那直接使用VPS作中为转进行穿透不好么,何况多此一举?没错,最好的方案就是这样,可以买一台国内的VPS专门用于穿透,但问题是国内的VPS价格贵啊,不差钱者该方案不适合。那么使用国外的VPS呢,当然也可以,但问题是国外VPS通常延迟较高,要实现远程桌面控制这些体验非常差。所以本方案使用国内家宽作中frps服务端,可以起到较小的延迟效果
GPT的回答如下:
在公网机器上安装 frps
和 ddclient
。
在 VPS 上运行一个服务来获取公网机器的 IP。
在内网机器上运行 frpc
,并动态更新 frps
的 IP 地址。
四 ChatGPT实现的代码
直接上调试过的代码:
1.VPS安装脚本文件获取上传的IP地址
如果VPS安装了宝塔,可以通过宝塔面板添加网站的方式进行,如果没有,按下列方式。
在 VPS 上的 web 服务器根目录(例如 /var/www/html
)中创建一个文件 update_ip.php
,用来接收并保存公网机器上传的 IP 地址。
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ip'])) {
$ip = $_POST['ip'];
file_put_contents('public_ip.txt', $ip);
echo 'IP updated';
} else {
echo 'Invalid request';
}
?>
该Php文件获取公网端脚本上传的最新ip地址,并保存在public_ip.txt文件中。
2.公网机器端安装自动上传ip的代码(openwrt适用)
公网机器安装frps不作描述了,不同设备均不同,按相应设备安装,或再问GPT。
以下是上传ip的脚本文件。
#!/bin/sh
# 获取公网 IP 地址
publicIP=$(curl -4 -s http://ifconfig.me/ip)
# 输出当前 IP 地址
echo "当前公网 IP 地址是: $publicIP"
# 检查 IP 是否有效并上传到 VPS
echo "$publicIP" | grep -q '[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+' && \
curl -s -X POST -d "ip=$publicIP" "你自己的VPS网址或IP地址/update_ip.php" || \
echo "Failed to retrieve or upload public IP"
解释:
- 获取公网 IP 地址:使用
curl -4 -s http://ifconfig.me/ip
获取公网 IP 地址,并将结果存储在publicIP
变量中。 - 输出当前 IP 地址:使用
echo "当前公网 IP 地址是: $publicIP"
输出当前获取到的公网 IP 地址。 - 检查 IP 是否有效并上传到 VPS:
- 使用
echo "$publicIP" | grep -q '[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+'
检查 IP 地址是否有效。 - 使用逻辑运算符
&&
连接检查结果和上传命令。如果 IP 地址有效,执行curl -s -X POST -d "ip=$publicIP" "http://ip.flybace.com/update_ip.php"
上传 IP 地址到 VPS。 - 使用逻辑运算符
||
连接检查结果和错误信息输出。如果 IP 地址无效或上传失败,执行echo "Failed to retrieve or upload public IP"
输出错误信息。
- 使用
使用方法如下:
将以上脚本保存为一个sh文件,如命名upload_ip.sh,将该sh文件上传到openwrt的一个目录,如/usr/bin/upload_ip.sh,添加定时任务:
* * * * * /bin/sh /usr/bin/upload_ip.sh,表示一分钟上传一次公网IP。
3.客户端安装frpc及配置自动更新IP脚本
1.客户端安装脚本
客户端安装frpc不作说明,自行安装 或问gpt。生成的代码如下(该代码经过多次调试,可成功运行):
# 设置 VPS 域名和 frpc 配置路径
$VPS_DOMAIN = "自己的域名或VPS的IP地址"
$FRPC_CONFIG_PATH = "C:\frp\frpc.toml(按实际填写)"
$FRPC_PATH = "C:\frp\frpc.exe(按实际填写)"
# 获取最新的 frps IP 地址
function Get-FrpsIp {
try {
$ip = Invoke-RestMethod -Uri "http://$VPS_DOMAIN/public_ip.txt"
return $ip.Trim() # 去除空白字符
} catch {
Write-Host "Error getting frps IP: $_"
return $null
}
}
# 更新 frpc 配置文件中的 serverAddr
function Update-FrpcConfig {
param (
[string]$ip
)
Write-Host "Updating frpc config with new IP: $ip"
$config = Get-Content -Path $FRPC_CONFIG_PATH -Raw
$updatedConfig = $config -replace '(serverAddr\s*=\s*".*")', "serverAddr = `"$ip`""
Set-Content -Path $FRPC_CONFIG_PATH -Value $updatedConfig -NoNewline
}
# 启动 frpc 服务
function Start-FRPC {
Write-Host "Starting frpc..."
Start-Process -FilePath $FRPC_PATH -ArgumentList "-c $FRPC_CONFIG_PATH" -NoNewWindow
}
# 停止 frpc 服务
function Stop-FRPC {
Write-Host "Stopping frpc..."
Get-Process -Name frpc -ErrorAction SilentlyContinue | ForEach-Object {
$_.CloseMainWindow()
Start-Sleep -Seconds 2
if (!$_.HasExited) {
$_.Kill()
}
}
}
# 获取 frps IP 并更新配置
$frpsIp = Get-FrpsIp
if ($frpsIp) {
Stop-FRPC
Start-Sleep -Seconds 5 # 确保 frpc 完全停止
Update-FrpcConfig -ip $frpsIp
Start-FRPC
} else {
Write-Host "Failed to get frps IP. Exiting script."
exit 1
}
# 持续监控 frps IP 变化
while ($true) {
$newFrpsIp = Get-FrpsIp
if ($newFrpsIp -and $newFrpsIp -ne $frpsIp) {
Write-Host "frps IP changed from $frpsIp to $newFrpsIp. Restarting frpc..."
Stop-FRPC
Start-Sleep -Seconds 5 # 确保 frpc 完全停止
Update-FrpcConfig -ip $newFrpsIp
Start-FRPC
$frpsIp = $newFrpsIp
} else {
Write-Host "frps IP is still $frpsIp. Waiting for change..."
}
Start-Sleep -Seconds 60
}
脚本详细说明:
- 变量定义:
$VPS_DOMAIN
: 定义 VPS 域名,用于获取最新的 frps IP 地址。$FRPC_CONFIG_PATH
: 定义 frpc 配置文件路径。$FRPC_PATH
: 定义 frpc 可执行文件路径。- 函数
Get-FrpsIp
:
- 尝试从指定的 URL 获取 frps 的 IP 地址。
- 如果成功,返回 IP 地址并去除任何空白字符。
- 如果失败,输出错误信息并返回
$null
。- 函数
Update-FrpcConfig
:
- 参数:新的 IP 地址
$ip
。- 读取现有的 frpc 配置文件内容。
- 使用正则表达式替换
serverAddr
的值为新的 IP 地址。- 将更新后的配置写回文件中,不添加额外的换行。
- 函数
Start-FRPC
:
- 输出 “Starting frpc…”。
- 使用
Start-Process
启动 frpc 进程,指定配置文件路径。- 函数
Stop-FRPC
:
- 输出 “Stopping frpc…”。
- 获取名为
frpc
的进程,尝试关闭每个进程的主窗口。- 等待 2 秒,如果进程未退出,则强制终止进程。
- 初始 frps IP 获取和配置更新:
- 获取当前 frps IP 地址。
- 如果成功,停止现有的 frpc 进程,更新配置文件并重新启动 frpc。
- 如果失败,输出错误信息并退出脚本。
- 持续监控 frps IP 变化:
- 脚本进入一个无限循环以监控 frps IP 的变化。
- 每次循环,获取新的 frps IP 地址。
- 如果 IP 地址发生变化,停止现有 frpc 进程,更新配置文件并重新启动 frpc。
- 如果 IP 地址未变,输出等待信息。
- 每次循环后等待 60 秒。
2.生成脚本后的使用方法
1.直接运行脚本方式:
将以上代码保存为如frpc.ps1,使用管理员命令运行脚本,如本脚本在C:\FRPgh ,进入该目录后运行,不要关闭对话框。
2.生成系统服务,系统重启后自动运行。
1.创建一个新的 BAT 文件,例如 start_monitor.bat
,并在其中包含以下内容:
@echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "C:\path\to\monitor_ip_change.ps1"
将 "C:\path\to\monitor_ip_change.ps1"
替换为您实际的 PowerShell 脚本路径。
2.下载并安装 NSSM
NSSM (Non-Sucking Service Manager) 是一个轻量级的工具,用于将任何可执行文件作为服务运行。您可以从 NSSM 的官方网站 下载并安装 NSSM。
3.使用 NSSM 创建服务
- 将 NSSM 解压缩到一个目录中,例如
C:\nssm
. - 打开命令提示符,以管理员身份运行。
- 使用以下命令创建服务:
C:\nssm\nssm.exe install MyMonitorService "C:\path\to\start_monitor.bat" 将 MyMonitorService 替换为您的服务名称,将 "C:\path\to\start_monitor.bat" 替换为实际的 BAT 文件路径。
运行后会显示生成服务成功。
- 启动服务
安装完成后,您可以通过以下命令启动服务:
net start MyMonitorService 或
nssm startMyMonitorService
也可以使用nssm的命令,要删除创建的程序必须使用的nssm的命令,基本命令如下,运行nssm命令时必须使用CMD的管理员模式并进入其安装目录。
nssm install FRPC-service "C:\frp\start-frpc-monitor.bat" #安装服务
nssm start FRPC-service #启动服务
nssm stop FRPC-service #停止服务
nssm status FRPC-service #查看服务状态
nssm remove FRPC-service #删除服务
nssm edit FRPC-service #设置服务
五 试运行
经过上述过程后,试运行效果如下:
当FRPS端的公网变化时,它会自动更新FRPC相关设置并保持连接。