如何将所有QEMU-KVM/Libvirt虚拟机流量通过主机上的V2Ray代理转发?
如何将所有QEMU-KVM/Libvirt虚拟机流量通过主机上的V2Ray代理转发?
我之前也碰到过一模一样的需求——让KVM虚拟机完全不用做任何配置,所有流量自动走主机的V2Ray代理。你之前的问题主要是只处理了TCP的80/443端口,像DNS这类UDP流量根本没被覆盖,而且普通的HTTP代理本来就没法处理UDP,得用透明代理方案才行。下面给你两种可行的方法,一种是用v2raya一键搞定,另一种是手动配置V2Ray和iptables,你可以选适合自己的:
方法一:用v2raya一键配置(最适合新手)
既然你已经用过v2raya,那这个方法最省心,它会自动帮你搞定所有规则:
- 打开v2raya的Web界面,进入「设置」页面
- 找到「全局透明代理」选项,选择「网卡模式」
- 在下拉菜单里选中
virbr0(就是libvirt默认的虚拟机网桥) - 保存设置,v2raya会自动配置iptables规则和V2Ray的透明代理参数
这样一来,所有通过virbr0进出的虚拟机流量(包括TCP和UDP)都会被自动转发到V2Ray代理,虚拟机里不用改任何设置,不管是浏览器还是dig命令,都会显示代理后的公网IP。
方法二:手动配置V2Ray+iptables(适合想深入了解的用户)
如果不想用v2raya,我们可以手动配置透明代理,步骤如下:
第一步:修改V2Ray配置文件,添加透明代理入口
找到你的V2Ray配置文件(通常是/etc/v2ray/config.json或者~/.config/v2ray/config.json),在inbounds里添加一个支持TCP/UDP的透明代理入口,同时调整路由规则:
{ "inbounds": [ // 保留你原来的SOCKS和HTTP代理入口 { "port": 10808, "protocol": "socks", "settings": { "auth": "noauth", "udp": true, "ip": "127.0.0.1" } }, { "port": 10809, "protocol": "http", "settings": { "auth": "noauth" } }, // 新增透明代理入口,端口自定义(比如12345) { "port": 12345, "protocol": "dokodemo-door", "settings": { "network": "tcp,udp", "followRedirect": true }, "streamSettings": { "sockopt": { "tproxy": "tproxy" } }, "tag": "transparent" } ], "outbounds": [ // 保留你原来的V2Ray服务器出口配置 { "protocol": "vmess", // 换成你实际用的协议,比如vless、trojan等 "settings": { "vnext": [ { "address": "你的V2Ray服务器IP", "port": 你的服务器端口, "users": [ { "id": "你的UUID", "alterId": 0, "security": "auto" } ] } ] }, "streamSettings": { "network": "tcp", // 换成你实际的传输方式,比如ws、grpc等 "security": "tls" }, "tag": "proxy" }, // 可选:添加直连出口,用于本地非代理流量 { "protocol": "freedom", "settings": {}, "tag": "direct" } ], "routing": { "rules": [ // 把透明代理入口的流量全部转发到V2Ray服务器 { "type": "field", "inboundTag": ["transparent"], "outboundTag": "proxy" } ] } }
修改完后重启V2Ray服务:
sudo systemctl restart v2ray
第二步:配置iptables规则,接管虚拟机所有流量
首先开启IP转发并保存配置(确保重启后生效):
sudo sysctl -w net.ipv4.ip_forward=1 sudo sysctl -w net.ipv6.conf.all.forwarding=1 sudo sysctl -w net.ipv4.conf.all.send_redirects=0 # 写入配置文件 echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf echo "net.ipv6.conf.all.forwarding=1" | sudo tee -a /etc/sysctl.conf echo "net.ipv4.conf.all.send_redirects=0" | sudo tee -a /etc/sysctl.conf sudo sysctl -p
然后配置TCP流量转发:
# 把virbr0进来的所有TCP流量重定向到透明代理端口 sudo iptables -t nat -A PREROUTING -i virbr0 -p tcp -j REDIRECT --to-port 12345
再配置UDP流量的TProxy转发(因为UDP不能直接用REDIRECT,需要用TProxy):
sudo iptables -t mangle -A PREROUTING -i virbr0 -p udp -j TPROXY --on-port 12345 --tproxy-mark 0x1/0x1 # 添加路由规则,让标记过的UDP流量走本地路由 sudo ip rule add fwmark 0x1 lookup 100 sudo ip route add local 0.0.0.0/0 dev lo table 100
如果需要支持IPv6,执行类似的IPv6规则:
sudo ip6tables -t mangle -A PREROUTING -i virbr0 -p udp -j TPROXY --on-port 12345 --tproxy-mark 0x1/0x1 sudo ip -6 rule add fwmark 0x1 lookup 100 sudo ip -6 route add local ::/0 dev lo table 100
第三步:测试效果
在虚拟机里执行以下命令,检查公网IP是否为代理IP:
# 测试TCP流量 curl ifconfig.me # 测试DNS流量 dig +short myip.opendns.com @resolver1.opendns.com
如果两者都显示代理后的IP,说明配置成功了!
备注:内容来源于stack exchange,提问作者Malvo
相关产品推荐
相关产品推荐

