如果觉得 Ngrok 收费,可以尝试 开源免费的内网穿透方案,例如使用 Frp(Fast Reverse Proxy)。以下是 基于 Frp 的自建内网穿透方案(无需 Python 代码,更稳定高效),以及 Python 实现内网穿透的原理分析(适合技术探索,但生产环境不推荐)。
一、自建 Frp 内网穿透
免费、稳定,推荐
1. 原理简介
Frp 是开源的反向代理工具,通过在公网服务器(VPS)部署服务端,本地设备运行客户端,将本地端口映射到公网服务器的指定端口,实现内网穿透。
支持多端口穿透(包括所有端口),支持 TCP、UDP、HTTP/HTTPS 等协议,性能稳定,配置灵活。
2. 所需条件
一台公网 IP 的服务器(VPS)(例如阿里云、腾讯云,最低配置即可,按流量计费更划算)。
本地电脑(客户端) 和 公网服务器(服务端) 均需安装 Frp。
3. 操作步骤
步骤 1:购买并配置公网服务器
购买 VPS:选择海外服务器(如 Linode、Vultr)或国内服务器(需备案),推荐 Ubuntu 系统。
配置防火墙:
# Ubuntu 示例(开放 7000、7001、80、443 等端口)
sudo ufw allow 7000/tcp
sudo ufw allow 7001/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
开放 Frp 服务端默认端口(如 7000 用于通信,7001 用于 Web 管理,其他端口按需开放)。
步骤 2:在公网服务器安装 Frp 服务端
下载 Frp:Frp 官方 Release 页面,选择对应系统版本(如
frp_0.49.0_linux_amd64.tar.gz
)。
wget https://github.com/fatedier/frp/releases/download/v0.49.0/frp_0.49.0_linux_amd64.tar.gz
tar -zxvf frp_0.49.0_linux_amd64.tar.gz
cd frp_0.49.0_linux_amd64
修改服务端配置文件(frps.ini):
[common]
bind_port = 7000 # 服务端与客户端通信的端口(必填)
dashboard_port = 7001 # Web 管理界面端口(可选)
dashboard_user = admin # 管理界面用户名(可选)
dashboard_pwd = admin # 管理界面密码(可选)
启动服务端:
./frps -c frps.ini
建议设置为系统服务(
systemd
),确保开机自启:
sudo cp frps.service /etc/systemd/system/ # 假设已创建服务文件
sudo systemctl enable frps
sudo systemctl start frps
步骤 3:在本地电脑安装 Frp 客户端
下载 Frp:根据本地系统(Windows/macOS/Linux)选择对应版本,例如 Windows 的
frp_0.49.0_windows_amd64.zip
。解压并修改客户端配置文件(frpc.ini):
[common]
server_addr = 公网服务器IP # 填写你的 VPS IP
server_port = 7000 # 对应服务端的 bind_port
# 示例 1:穿透本地 8080 端口到公网服务器的 80 端口(HTTP 服务)
[web]
type = tcp
local_ip = 127.0.0.1 # 本地服务 IP(通常为 localhost)
local_port = 8080 # 本地需穿透的端口
remote_port = 80 # 公网服务器映射的端口(需与防火墙开放的端口一致)
# 示例 2:穿透本地 3389 端口(远程桌面)到公网服务器的 3389 端口
[rdp]
type = tcp
local_port = 3389
remote_port = 3389
# 示例 3:穿透所有端口(TCP 全端口映射,谨慎使用!)
# 注意:全端口映射需服务端和客户端配置支持,且可能存在安全风险
[all-ports]
type = tcp
local_ip = 0.0.0.0 # 监听所有本地 IP
local_port = 1-65535 # 本地端口范围(所有端口)
remote_port = 10000-75535 # 公网服务器端口范围(需足够大且未被占用)
启动客户端:
Windows:双击
frpc.exe -c frpc.ini
或通过命令行启动。Linux/macOS:
./frpc -c frpc.ini
步骤 4:访问公网服务
穿透后,通过
公网服务器IP:远程端口
访问本地服务。例如:
本地 Web 服务:
http://公网IP:80
(对应示例 1)。远程桌面:连接
公网IP:3389
(对应示例 2)。
二、Python 实现
内网穿透的原理(技术探索)
如果想通过 Python 代码实现内网穿透(适合学习原理,但生产环境不推荐,性能和稳定性较差),核心思路是 利用 socket 转发流量,分为以下步骤:
1. 原理概述
公网服务器作为中转站:本地客户端(内网设备)与公网服务器建立长连接,公网服务器接收外部请求后,通过该连接将数据转发给本地客户端,实现反向代理。
核心模块:
socket
(网络通信)、threading
(多线程处理并发连接)。
2. 简单实现示例(TCP 单端口穿透)
公网服务器端代码(server.py)
import socket
import threading
# 公网服务器监听端口(需开放防火墙)
SERVER_PORT = 7000
# 本地客户端 IP(需提前通过客户端注册)
LOCAL_IP = "192.168.1.100" # 假设本地客户端 IP
LOCAL_PORT = 8080 # 本地需穿透的端口
def handle_client(client_sock):
# 与本地客户端建立连接
local_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
local_sock.connect((LOCAL_IP, LOCAL_PORT))
except Exception as e:
client_sock.sendall(b"Local connection failed")
client_sock.close()
local_sock.close()
return
# 转发数据(客户端 <-> 本地服务)
def forward_to_local():
while True:
data = client_sock.recv(1024)
if not data:
break
local_sock.sendall(data)
client_sock.close()
local_sock.close()
def forward_to_client():
while True:
data = local_sock.recv(1024)
if not data:
break
client_sock.sendall(data)
client_sock.close()
local_sock.close()
# 启动双向转发线程
threading.Thread(target=forward_to_local).start()
threading.Thread(target=forward_to_client).start()
def main():
server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_sock.bind(("0.0.0.0", SERVER_PORT))
server_sock.listen(5)
print(f"Server listening on port {SERVER_PORT}...")
while True:
client_sock, addr = server_sock.accept()
print(f"New connection from {addr}")
threading.Thread(target=handle_client, args=(client_sock,)).start()
if __name__ == "__main__":
main()
本地客户端代码(client.py)
import socket
# 公网服务器 IP 和端口
SERVER_IP = "公网服务器IP"
SERVER_PORT = 7000
def main():
# 与公网服务器建立长连接(保持心跳)
while True:
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((SERVER_IP, SERVER_PORT))
print("Connected to server")
# 保持连接(心跳机制,防止断开)
while True:
sock.sendall(b"heartbeat")
sock.recv(1024)
except Exception as e:
print(f"Connection failed: {e}")
sock.close()
if __name__ == "__main__":
main()
3. 代码原理说明
公网服务器端:
监听指定端口,接收外部请求(如浏览器访问)。
与本地客户端建立连接,通过 多线程双向转发数据(外部请求 → 公网服务器 → 本地服务;本地响应 → 公网服务器 → 外部客户端)。
本地客户端:
主动连接公网服务器,维持长连接(需添加心跳机制防止断开)。
作为数据接收端,将公网服务器转发的数据传递给本地服务。
局限性:
仅支持单端口穿透,多端口需为每个端口创建独立连接。
无身份验证,存在安全风险(需手动添加 token 校验)。
性能差:Python 的 socket 转发效率低,无法处理高并发或大流量场景。
三、方案对比与建议
四、注意事项
安全风险:
全端口穿透可能暴露内网服务,建议仅穿透必要端口,并在公网服务器设置防火墙规则。
使用 Frp 时,建议启用 token 认证 和 TLS 加密(参考 Frp 官方文档)。
性能优化:
Frp 支持 TCP 复用、压缩 等优化配置,可提升传输效率。
公网服务器选择与本地网络延迟低的节点(如国内服务器优先选择阿里云上海/北京节点)。
替代方案:
若需更简单的免费方案,可尝试 Netcat(nc) 或 Serveo(无需服务器,但稳定性较差)。
总结
推荐优先使用 Frp:配置简单、功能完善,适合长期稳定的内网穿透需求。
Python 实现仅用于学习:生产环境中不建议使用,如需自定义功能,可基于 Frp 源码进行二次开发。
如果需要进一步优化配置或解决问题,可以提供具体环境信息(如系统版本、网络架构),我会给出更详细的方案!
评论区