|
|
我原本的用法,是网关192.168.1.1上有dnsmasq,作为局域网各主机的dns服务。然后用iptables tproxy所有流量到xray,xray里面对53端口的包设置路由规则到内置dns模块,由dns模块根据规则选择是去8.8.8.8还是本地联通的dns查询。
这样的用法很快遇到一个致命问题,就是IP_TRANSPARENT冲突,原因是:
一、冲突原理(网络资料总结)
- Xray 透明代理(TProxy)机制
Xray 开启 IP_TRANSPARENT 选项后,为处理透明代理的 UDP 流量(尤其是 DNS 53 端口),会创建临时 UDP socket 并绑定 0.0.0.0:53(或特定地址),用于接收被 iptables/nftables 重定向到 Xray 的 DNS 查询。 - 端口独占与内核匹配规则
- Linux 内核对 UDP 端口采用完全匹配(五元组 / 四元组)+ 最佳匹配原则。
- IP_TRANSPARENT socket 优先级更高:它可绑定非本机地址、接收任意目标地址的 53 端口流量。
- 若 dnsmasq 先启动,Xray 会通过 TProxy 机制抢占 53 端口的流量处理权,导致 dnsmasq 收不到请求。
表现就是dnsmasq无法回包给局域网的客户端,导致dns查询失败。
为了解决这个问题,考虑改用tun模式,就是在系统里虚拟一个tun网卡,xray绑定在tun上,所有需要翻墙的客户端的流量转给tun网卡,就和本机的dnsmasq不冲突了。
去查询资料的时候,居然找不到任何一个对xray tun模式的引导讲解文章,于是摸索了半天,终于搞定了配置,主要的点如下:
1:系统iptables配置:
# 1. 仅 1~99 走 系统的SNAT,100~254 不走这条,走tun代理
# 注意,这里的流量,包含了1-99自己发起的出外网包,也包含了1-99的服务器回给外网客户端的包,两种包都会命中这个规则
# 网关192.168.1.1 自身的上网包,不走这个命令,因为标准系统服务比如dnsmaq和nslookup,会直接绑定ppp0的ip发包;而特殊的比如singbox,会绑定自己的10.x ip
# 反正没有本机进程会绑定192.168.1.1或者127.0.0.1,一般只有伪装包才会这样
iptables -t nat -I POSTROUTING -m iprange --src-range 192.168.1.1-192.168.1.99 -o ppp0 -j MASQUERADE
# 2.2.1发到192.168.1.1:53的包,修改目标ip为1.1.1.1,以便被tun0读取和劫持dns
# mangle 的 PREROUTING 在 nat 的 PREROUTING 之前处理,因此先打标记后做 DNAT 是可行的。
iptables -t mangle -A PREROUTING -m mark --mark 232 -j RETURN
iptables -t mangle -A PREROUTING -m iprange --src-range 192.168.1.100-192.168.1.254 -d 192.168.1.1 -p udp --dport 53 -j MARK --or-mark 232
iptables -t nat -A PREROUTING -m iprange --src-range 192.168.1.100-192.168.1.254 -d 192.168.1.1 -p udp --dport 53 -j DNAT --to-destination 1.1.1.1
# 2.2.2: 100-254的上网发包,用于非53的
# 100~254 主动上网流量,进 TUN 代理
# 直接打or mark,走ip rule
iptables -t mangle -A PREROUTING -m iprange --src-range 192.168.1.100-192.168.1.254 ! -d 192.168.1.0/24 -j MARK --or-mark 232
#凡是mark232的,都去查路由表233
ip rule add fwmark 232 table 233 priority 123
# 等待 tun0 出现
while ! ip link show tun0 >/dev/null 2>&1; do
sleep 0.5
done
#233路由表只有一个默规则,就是都去tun0
ip addr add 10.255.0.1/30 dev tun0
ip link set tun0 up
ip route add default dev tun0 table 233
sysctl -w net.ipv4.conf.all.rp_filter=2
sysctl -w net.ipv4.conf.enp8s0.rp_filter=2
sysctl -w net.ipv4.conf.tun0.rp_filter=2
注意,每次restart xray服务,都要重新执行这三句:
ip addr add 10.255.0.1/30 dev tun0ip link set tun0 up
ip route add default dev tun0 table 233
因为tun在xray重启时会被删掉,重启后也没有自己赋值ip
2: xray的config
"inbounds": [
//tun 透明代理
{
"port": 0,
"protocol": "tun",
"tag": "ipt-in",
"settings": {
"name": "tun0",
"mtu": 1492,
"udp_fullcone": true // UDP FullCone NAT,提升游戏/语音体验
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"],
"domainsExcluded": [ "courier.push.apple.com", "push.apple.com", "apple.com.cn" ]
}
}
],
"outbounds": [
{ //隐藏的路由规则:当入站流量不符合任何条件时,转发给第一个出站
"tag": "direct",
"protocol": "freedom",
"settings": {
"domainStrategy": "UseIPv4"
},
"streamSettings": {
"sockopt": {
"mark": 2
}
}
},
{ //翻墙出站
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "43.111.111.111",
"port": 34444,
"users": [
{
"id": "d55555555-6666-7777-8788-1c333333333",
"flow": "xtls-rprx-vision", //升级1.8.10修改
"encryption": "none"
}
]
}
]
},
//升级1.8.10修改
"streamSettings": {
"network": "tcp",
"security": "tls", // 必须改tls(或reality)
"tlsSettings": { // 替换xtlsSettings为tlsSettings
"serverName": "abc.com", // 保留域名,和证书一致
"insecure": false, // 生产环境false
"alpn": ["h2", "http/1.1"] // 官方推荐的ALPN
},
"sockopt": {
"mark": 2,
"interface": "ppp0" //tun 模式新增,绑定外网网卡,避免死循环
}
}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {
"response": {
"type": "http"
}
}
},
{ //被劫持的53端口流量走这里,protocol": "dns",意思是用DNS模块来解析
"tag": "dns-out",
"protocol": "dns",
"streamSettings": {
"sockopt": {
"mark": 2
}
}
}
],
"dns": {
"queryStrategy": "UseIPv4",
"disableFallback": true,
"disableFallbackIfMatch": true,
"disableCache": true,
"optimisticCache": false,
"enableParallelQuery": true,
"tag": "dns-in",
"hosts": {
"abc.com": "43.111.111.111"
},
"servers": [
{
"address": "223.5.5.5", //阿里DNS
"domains": [
"geosite:cn",
//"geosite:apple-cn",
"akadns.net",
"mzstatic.com",
"afreecatv.com",
"download.epicgames.com",
"steamcontent.com"
],
"skipFallback": true
//"expectIPs": ["geoip:cn"] //必须匹配到国内ip才ok
},
{
"address": "8.8.8.8",
"domains": [
"geosite:geolocation-!cn",
"s.tgfcer.com",
"jable.tv",
"www.gstatic.com",
"fonts.gstatic.com"
],
"skipFallback": true
},
{//如果之前的规则没命中,则走这个dns
"address": "1.1.1.1",
"skipFallback": true
}
]
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{//劫持所有的53端口流量,强制导入到内置dns去解析
"type": "field",
"inboundTag": ["ipt-in"],
"port": 53,
"outboundTag": "dns-out"
},
{//这些ip也全程走proxy,避免途中被dns污染
"type": "field",
"inboundTag": ["dns-in"],
"ip": ["8.8.8.8", "8.8.4.4", "1.1.1.1", "1.0.0.1"],
"outboundTag": "proxy"
},
{
"type": "field",
"inboundTag": ["dns-in"],
"ip": [
"223.5.5.5/32",
"119.29.29.29/32",
"180.76.76.76/32",
"202.106.195.68/32",
"202.106.46.151/32",
"114.114.114.114/32"
],
"outboundTag": "direct"
},
{
"type": "field",
"inboundTag": ["ipt-in"],
"ip": "43.111.111.111",
"outboundTag": "direct"
},
{
"type": "field",
"inboundTag": ["ipt-in"],
"domain": ["abc.com"],
"outboundTag": "direct"
},
{
"type": "field",
"inboundTag": ["ipt-in"],
"protocol": ["bittorrent"],
"outboundTag": "direct"
},
{
"type": "field",
"inboundTag": ["ipt-in"],
"domain": [
"geosite:cn",
//"geosite:apple-cn",
"akadns.net",
"mzstatic.com",
"afreecatv.com",
"download.epicgames.com",
"steamcontent.com"
],
"outboundTag": "direct"
},
{
"type": "field",
"inboundTag": ["ipt-in"],
"domain": [
"geosite:geolocation-!cn",
"s.tgfcer.com",
"jable.tv",
"www.gstatic.com",
"fonts.gstatic.com"
],
"outboundTag": "proxy"
},
{
"type": "field",
"inboundTag": ["ipt-in"],
"ip": ["geoip:cn", "geoip:private"],
"outboundTag": "direct"
}
]
}
|
|