创建自己的2^64个IP的代理池
本文主要内容在
/64IPv6 地址块的服务器上部署go-proxy-ipv6-pool随机出口 IP 代理服务。解决运行后却遭遇的connection timed out或cannot assign requested address错误。这通常不是代理程序本身的问题,而是服务器网络环境没有进行正确配置。
本文将详细记录从零开始部署一个 Go IPv6 代理池,并彻底解决其网络连接问题的全过程。
组件说明
- Golang:运行项目。
- ndppd:类似于 IPv4 中
ARP协议的作用,IPv6 中需要使用ND协议来发现邻居并确定可用路径。
部署流程
基本步骤
第一步:基础环境和代理程序准备
首先,我们需要准备好 Go 环境并下载代理程序项目。
1. 安装 Go 语言环境
# 下载 Go (请到官网 https://go.dev/dl/ 获取最新版链接)wget https://go.dev/dl/go1.22.3.linux-amd64.tar.gz
# 解压到 /usr/localsudo tar -C /usr/local -xzf go1.22.3.linux-amd64.tar.gz
# 将 Go 的二进制文件路径添加到环境变量echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profilesource ~/.profile
# 验证安装go version2. 克隆项目并准备运行脚本
# 克隆项目git clone https://github.com/XiaoMiku01/go-proxy-ipv6-pool.gitcd go-proxy-ipv6-pool
# 创建一个便捷的 run.sh 脚本cat << 'EOF' > run.sh#!/bin/bash
# 将 Go 的缓存目录设置在当前项目下,避免污染系统export GOMODCACHE="$(pwd)/.gomodcache"export GOCACHE="$(pwd)/.gocache"mkdir -p $GOMODCACHEmkdir -p $GOCACHE
echo "--- Using local Go caches ---"echo "Module Cache: $GOMODCACHE"echo "Build Cache: $GOCACHE"echo "-----------------------------"
# 以 root 权限运行 Go 程序,并将所有脚本参数传递给它# 注意:后面的网络配置需要程序以 root 权限运行来绑定 IP# 如果不使用自动绑定IP的修改版,可以不用 sudosudo go run . "$@"EOF
# 赋予脚本执行权限chmod +x run.sh第二步:核心网络配置
这是解决所有网络问题的核心。我们需要从内核 Socket 层、路由层到数据链路层进行“三板斧”配置。
1. 内核参数:允许绑定非本地 IP (解决 cannot assign requested address)
- 问题:默认情况下,Linux 内核不允许程序绑定到一个尚未明确分配给网络接口的 IP 地址。
- 解决方案:修改
net.ipv6.ip_nonlocal_bind参数。
# 临时启用(用于测试,重启后失效)sudo sysctl -w net.ipv6.ip_nonlocal_bind=1
## 同时修改下其他参数sudo sysctl -w net.ipv6.conf.all.forwarding=1sudo sysctl -w net.ipv6.conf.default.forwarding=1
# 永久生效sudo tee -a /etc/sysctl.conf <<EOFnet.ipv6.ip_nonlocal_bind=1net.ipv6.conf.all.forwarding=1net.ipv6.conf.default.forwarding=1EOF \&& sudo sysctl -p2. 本地路由:告知内核 /64 网段归本机所有 (解决出站路由)
- 问题:内核需要知道它可以从
/64地址池中的任意 IP 发出数据包。 - 解决方案:添加一条本地路由规则。
# 临时添加(用于测试,重启后失效)# 将 <your_ipv6_cidr> 替换为你的网段# 将 <interface> 替换为你的网卡名,例如 eth0sudo ip route add local <your_ipv6_cidr> dev <interface>
# 永久生效sudo nano /etc/network/interfaces.d/xx-cloud-init
# 找到 iface eth0 inet6 static 这部分,在它的末尾添加 post-up 命令。post-up 的意思是“当这个接口成功启动后,执行以下命令”。# ... (前面的配置不变) ...
# control-alias eth0iface eth0 inet6 static address xxxxx gateway xxxxx # 在这里添加 post-up 命令 post-up ip route add local <your_ipv6_cidr> dev <interface>
# 重启服务sudo systemctl restart networking.service3. NDP 代理:响应路由器的邻居请求 (解决入站路由和 connection timed out)
- 问题:当外部服务器响应你的请求时,你的服务商路由器需要通过邻居发现协议(NDP)找到你那个随机 IP 对应的 MAC 地址。默认情况下,你的服务器不会对未明确绑定的 IP 进行应答。
- 解决方案:使用
ndppd(NDP Proxy Daemon) 自动应答所有来自你子网的 NDP 请求。
# 安装 ndppdsudo apt install -y ndppd
# 编辑配置文件sudo nano /etc/ndppd.conf
# 清空文件内容,然后粘贴以下为你定制的配置# 同样,替换 <your_ipv6_cidr> 和 <interface># --- ndppd.conf start ---route-ttl 30000
proxy <interface> { router no timeout 500 ttl 30000 rule <your_ipv6_cidr> { static }}# --- ndppd.conf end ---
# 重启并设置开机自启sudo systemctl restart ndppdsudo systemctl enable ndppd
# 检查服务状态,确保 active (running)sudo systemctl status ndppd第三步:启动代理并进行最终测试
所有配置完成后,我们可以启动代理并验证它是否按预期工作。
1. 启动代理服务
在 go-proxy-ipv6-pool 目录下执行:
# 假设你的 HTTP 代理端口是 52122,SOCKS5 是 52123# CIDR 替换成你自己的./run.sh --port 52122 --cidr <your_ipv6_cidr>2. 循环测试 打开一个新的终端窗口,运行下面的命令来持续测试代理,并观察出口 IP 是否在变化:
# 将端口号 52122 替换为你自己设置的 HTTP 端口while true; do curl -s \ -w "\n--- Timing Info ---\nHttpCode: %{http_code}\nTotal Time: %{time_total}s\n---------------------\n" \ -x http://localhost:52122 \ --connect-timeout 5 \ ipv6.ip.sb sleep 0.5done如果一切正常,你将看到屏幕上不断打印出不同的、来自你 /64 地址池的 IPv6 地址,并且没有任何报错。
结论
部署一个功能完备的 IPv6 代理池,关键不在于应用本身,而在于对底层网络环境的深刻理解和正确配置。通过 ip_nonlocal_bind、local route 和 ndppd 这“三板斧”,我们成功地解决了从内核到网络的各层障碍,实现了应用的预期功能。希望这篇指南能帮助到遇到同样问题的朋友们。
部分内容可能已过时
Lim's Blog