zfl9 / dns2tcp

将 dns 查询从 udp 转为 tcp 的实用工具
GNU Affero General Public License v3.0
133 stars 54 forks source link

旁路由不支持tproxy没有mangle表,可以通过如下方式解决DNS污染问题吗 #12

Closed Angel0726 closed 6 months ago

Angel0726 commented 6 months ago

我希望设置一个旁路由实现上网功能,但是小主机不支持tproxy也没有mangle表。我想怎么解决DNS污染问题。

  1. 设置v2ray
  2. 设置iptables
    iptables -t nat -A v2ray -p tcp -j REDIRECT --to-ports 1099
    iptables -t nat -I PREROUTING -p tcp -j v2ray

    到这一步局域网内的设备已经能够继续进行科学上网。

  3. dns2tcp
    dns2tcp -L "127.0.0.1#5353" -R "8.8.8.8#53"
    iptables -t nat -A OUTPUT -p PREROUTING -d 8.8.8.8 --dport 53 -j REDIRECT --to-ports 1099

    通过上面的命令能够解决DNS污染问题呢,怎么验证是否解决了DNS污染问题

zfl9 commented 6 months ago

没看懂你的 dns2tcp 用在了哪里,5353 端口在什么地方使用了?

Angel0726 commented 6 months ago

没看懂你的 dns2tcp 用在了哪里,5353 端口在什么地方使用了?

我确实配置错了。需求也不太清晰。

iptables设置。因为系统不支持tproxy,也没有mangle表,所以只设置了tcp转发。

  iptables -t nat -A v2ray -p tcp -j REDIRECT --to-ports 1099
  iptables -t nat -I PREROUTING -p tcp -j v2ray
zfl9 commented 6 months ago

慢是因为没分流吧(IP分流、DNS分流),分流就是指:国内IP、DNS不走代理,国外的才走代理。不然国内的网站肯定绕一圈。

zfl9 commented 6 months ago

iptables设置。因为系统不支持tproxy,也没有mangle表,所以只设置了tcp转发。

不支持 tproxy && 没有 mangle 表 应该不是导致慢的原因,因为没有这些,也可以正常配置“透明代理”,也就是 tcponly 模式(依赖 nat 表就可以了)

Angel0726 commented 6 months ago

慢是因为没分流吧(IP分流、DNS分流),分流就是指:国内IP、DNS不走代理,国外的才走代理。不然国内的网站肯定绕一圈。 在v2ray中有配置 出口

"outbounds": [
{
"tag": "naive",    # 第一个是默认出口协议
"protocol": "socks",
"settings": {
"servers": [
{
"address": "127.0.0.1",
"port": 1080
}
]
}
},
{
"protocol": "freedom",
"settings": {},
"tag": "direct",
"streamSettings": {
"sockopt": {
"mark": 255
}
}
}
],

路由

    "routing": {
        "strategy": "rules",
        "domainStrategy": "IPIfNonMatch",
        "settings": {
            "rules": [
                {
                    "type": "field",
                    "ip": [
                        "geoip:private"
                    ],
                    "outboundTag": "direct"
                },
                {
                    "type": "field",
                    "outboundTag": "naive",
                    "domain": [
                        "geosite:geolocation-!cn",
                        "geosite:tiktok",
                        "geosite:google",
                        "geosite:telegram",
                        "geosite:facebook",
                        "geosite:netflix",
                        "geosite:twitter",
                        "geosite:fastly",
                        "geosite:bing",
                        "geosite:github",
                        "domain:sspanel.net",
                        "domain:nivod4.tv",
                        "domain:nivod6.tv",
                        "domain:nivodz.com",
                        "domain:youtobe.com"
                    ]
                },
                {
                    "type": "field",
                    "ip": [
                        "geoip:cn"
                    ],
                    "outboundTag": "direct"
                },
                {
                    "type": "field",
                    "domain": [
                        "ip138.com",
                        "ifconfig.me",
                        "geosite:cn",
                        "geosite:alibaba",
                        "geosite:aliyun",
                        "geosite:alibabacloud",
                        "geosite:baidu",
                        "geosite:bilibili",
                        "geosite:cctv",
                        "geosite:chinanews",
                        "geosite:chinapower",
                        "geosite:cnki",
                        "geosite:csdn",
                        "geosite:ctrip",
                        "geosite:didi",
                        "geosite:douban",
                        "geosite:douyu",
                        "geosite:geolocation-cn",
                        "geosite:iqiyi",
                        "geosite:kugou",
                        "geosite:meitu",
                        "geosite:meituan",
                        "geosite:meizu",
                        "geosite:oneplus",
                        "geosite:oppo",
                        "geosite:sina",
                        "geosite:sohu",
                        "geosite:tencent",
                        "geosite:juejin",
                        "geosite:eastmoney",
                        "geosite:tld-cn",
                        "domain:vabc.top",
                        "domain:wsxlkj.cf",
                        "domain:dnspod.cn",
                        "domain:gov.cn"
                    ],
                    "outboundTag": "direct"
                },
                {
                    "type": "field",
                    "outboundTag": "naive",
                    "network": "tcp,udp"
                }
Angel0726 commented 6 months ago

tcponly

tcponly模式如何完成dns解析,使用dns2tcp?

zfl9 commented 6 months ago

那应该就是 DNS 没分流导致的慢了。

Angel0726 commented 6 months ago

那应该就是 DNS 没分流导致的慢了。

有dns分流,但是配置有问题吗。

    "dns": {
        "servers": [
            {
                "address": "https://1.1.1.1/dns-query",
                "domains": [
                    "geosite:geolocation-!cn"
                ],
                "expectIPs": [
                    "geoip:!cn"
                ]
            },
            {
                "address": "114.114.114.114",
                "port": 53,
                "domains": [
                    "geosite:cn",
                    "geosite:category-games@cn"
                ],
                "expectIPs": [
                    "geoip:cn"
                ],
                "skipFallback": true
            },
            {
                "address": "localhost",
                "skipFallback": true
            },
            "8.8.8.8"
        ]
    },
zfl9 commented 6 months ago

透明代理的核心就是分流,具体的:


我看你确实做了 DNS分流、IP分流,如果还感觉慢,那应该是你的旁路由性能不行,撑不起 v2ray 这种 golang 程序,建议将 IP 分流放到 iptables 层面(使用 ipset),降低 v2ray 分流带来的 cpu 负载。

因为这种 应用层(用户态)的分流 会损耗 直连 流量的性能,因为必须经过 v2ray 的一层转发,这里面涉及多次内存拷贝,系统调用(上下文切换)开销,在机器性能高的情况下可能感觉不到什么,如果机器性能不够(特别是嵌入式设备、路由器),这个开销是非常可观的。

所以我个人倾向于 内核态 的分流,具体到 Linux,就是利用 netfilter(iptables/nftables) 来分流,只要 iptables/nftables 规则配置得当,开销就几乎忽略不计。

zfl9 commented 6 months ago

有dns分流,但是配置有问题吗。

不清楚具体 v2ray 配置,我只对 iptables 分流、chinadns-ng 分流比较熟悉 😂

Angel0726 commented 6 months ago

有dns分流,但是配置有问题吗。

不清楚具体 v2ray 配置,我只对 iptables 分流、chinadns-ng 分流比较熟悉 😂

嗯嗯,没关系。其实我特别想知道下面的设置是不是可以实现udp的透明代理。

  1. 网上许多教程说udp必须使用tproxy,因为redirect会修改udp的地址,如果使用下面的转发能够实现udp的透明代理吗?:
    iptables -t nat -A v2ray -p udp -j REDIRECT --to-ports 1099
    iptables -t nat -I PREROUTING -p udp -j v2ray
  2. 我看你在文档中写了,是不是这种形式只能实现本机udp的转发(不用修改源地址)? image
zfl9 commented 6 months ago

网上许多教程说udp必须使用tproxy,因为redirect会修改udp的地址,如果使用下面的转发能够实现udp的透明代理吗?:

不可以,udp透明代理必须使用 TPROXY。

zfl9 commented 6 months ago

我看你在文档中写了,是不是这种形式只能实现本机udp的转发(不用修改源地址)?

这里的意思不是“udp透明代理”,而是对 dns 查询消息进行“透明的” udp to tcp 转换。

Angel0726 commented 6 months ago

网上许多教程说udp必须使用tproxy,因为redirect会修改udp的地址,如果使用下面的转发能够实现udp的透明代理吗?:

不可以,udp透明代理必须使用 TPROXY。

明白了,谢谢

zfl9 commented 6 months ago

就算没有 TPROXY,纯 TCP 透明代理也够了,因为大部分流量都是 TCP(http、https),UDP 也就是 DNS 占大头,这里只需要使用 dns2tcp 等工具,将 DNS 查询从 UDP 转换为 TCP,就可以接入 TCP 透明代理了。

Angel0726 commented 6 months ago

网上许多教程说udp必须使用tproxy,因为redirect会修改udp的地址,如果使用下面的转发能够实现udp的透明代理吗?:

不可以,udp透明代理必须使用 TPROXY。

我只搭建tcp代理,局域网内设备的网关、dns设置到 tcp代理主机,却可以进行科学上网。这是为什么呢,域名解析不应该出问题吗?域名解析不应该用到udp吗

zfl9 commented 6 months ago

因为你使用了 DoH,看你的 v2ray 这行配置:

           "address": "https://1.1.1.1/dns-query",

DoH,也就是通过 https 查询 dns,自然就是走 TCP 协议了。

和 dns2tcp 的作用一样,只是不同的实现方式,目的都是 UDP to TCP。

zfl9 commented 6 months ago

所以如果你感觉慢,那就是 v2ray 分流的性能问题(主要是 IP 分流吧,DNS 分流也有点影响,但没有 IP 分流这般明显)

Angel0726 commented 6 months ago

2ray -p udp -j REDIRECT --to-ports 1099 iptables -t nat -I PREROUTING -p udp -j v2ray

graph LR
A[局域网内设备]-->B[Iptables转发]
B--tcp-->C[v2ray 的https域名解析]

我在B阶段只设置了tcp转发到v2ray,udp怎么走到的v2ray呀。

iptables -t nat -A v2ray -p tcp -j REDIRECT --to-ports 1099
iptables -t nat -I PREROUTING -p tcp -j v2ray

局域网内的设备怎么通过v2ray完成的域名解析呢?局域网内设备的udp被转发到哪里了

graph LR
A[局域网内设备]-->B[Iptables转发]
B--tcp-->C[v2ray 的https域名解析]
B--udp-->D[???]
zfl9 commented 6 months ago

udp怎么走到的v2ray呀。

没有走到 v2ray 吧,iptables 这边都没设置相关规则。

局域网内的设备怎么通过v2ray完成的域名解析呢

不清楚,建议问下 v2ray 社区的

Angel0726 commented 6 months ago

局域网内的设备怎么通过v2ray完成的域名解析呢

不清楚,建议问下 v2ray 社区的

在不使用tproxy、mangle的情况下,你有办法完成局域网内设备的dns解析吗(tcponly模式?)

zfl9 commented 6 months ago

ss-tproxy 的 tcponly 模式,不涉及 mangle 表,不涉及 TPROXY。

IP分流:使用 iptables + ipset(chnroute),不经过 v2ray 等用户态进程,性能开销低。

DNS分流:使用 chinadns-ng,减少域名匹配带来的 CPU 开销,降低 DNS 解析延迟。

tcponly 模式下,目前会使用 dns2tcp 作为 chinadns-ng 的国外上游,接入 TCP 透明代理。

Angel0726 commented 6 months ago

ss-tproxy 的 tcponly 模式,不涉及 mangle 表,不涉及 TPROXY。

IP分流:使用 iptables + ipset(chnroute),不经过 v2ray 等用户态进程,性能开销低。

DNS分流:使用 chinadns-ng,减少域名匹配带来的 CPU 开销,降低 DNS 解析延迟。

tcponly 模式下,目前会使用 dns2tcp 作为 chinadns-ng 的国外上游,接入 TCP 透明代理。

我用的是arm小主机,内核缺很多模块,且不具备升级内核能力。使用ss-tproxy的仓库。问题很多 https://github.com/zfl9/ss-tproxy/issues/263 image

zfl9 commented 6 months ago

使用 tcponly='true' 配置,默认配置会触及 TPROXY(mangle表)

Angel0726 commented 6 months ago

数据流是这样吗?chinadns-ng是一个dns服务器吗?

graph LR
A[局域网内设备]--dns-->C[主机dns服务器]
C-->B[chinadns-ng]
B-->D[dns2tcp]
zfl9 commented 6 months ago

chinadns-ng是一个dns服务器吗?

是的,一个专用于 大陆透明代理 的 DNS 分流器。

zfl9 commented 6 months ago

DNS 解析流程:

-> 局域网内客户机发起 DNS 查询,默认是 UDP 协议 -> ss-tproxy 的 dnsmasq,上游是 chinadns-ng,dnsmasq 主要是起缓存作用 -> ss-tproxy 的 chinadns-ng,负责分流/操作ipset,两组上游(国内+国外) -> ss-tproxy 的 dns2tcp,用于 tcponly 模式,作为 chinadns-ng 的国外上游 -> ss-tproxy 的 TCP 透明代理

后续版本会将 dnsmasq 和 dns2tcp 移除,只用一个 chinadns-ng。

Angel0726 commented 6 months ago

dnsmasq是53端口吗?

zfl9 commented 6 months ago

是的,局域网内的机器,将 网关 && DNS 指向 ss-tproxy 主机,那么这些主机发起的 DNS 查询,自然就会来到 ss-tproxy 主机的 53 端口。接入 dnsmasq。

作为实现细节,在 ss-tproxy 中,如果 dns_mainport 非 53,会自动使用 iptables 重定向过去,使用者不用管这个。

Angel0726 commented 6 months ago

是的,局域网内的机器,将 网关 && DNS 指向 ss-tproxy 主机,那么这些主机发起的 DNS 查询,自然就会来到 ss-tproxy 主机的 53 端口。接入 dnsmasq。

作为实现细节,在 ss-tproxy 中,如果 dns_mainport 非 53,会自动使用 iptables 重定向过去,使用者不用管这个。

还有一个问题,就是如果局域网内来的数据没有匹配上网关的任何一条iptables会怎么样,会直接转发出去吗?

zfl9 commented 6 months ago

是的(只要开了 ip_forward)

Angel0726 commented 6 months ago

是的(只要开了 ip_forward)

那如果dns设置的网关地址,且没有匹配上网关的任何一条iptables。dns就会使用网关dns进程,例如systemd-resolve、dnsmasq

zfl9 commented 6 months ago

dns和iptables规则没有直接关系,你系统设置的什么DNS(linux下是/etc/resolv.conf,windows下是网络适配器/属性/DNS),那么dns query就发给谁。

zfl9 commented 6 months ago

和 iptables 规则有直接关系的是 IP分流 DNS 只是一个普通的应用层协议。

Angel0726 commented 6 months ago

谢谢,已解决dns问题