vernesong / OpenClash

A Clash Client For OpenWrt
MIT License
17.53k stars 3.18k forks source link

[Bug] UDP DNS返回结果超过512字节时用TCP重新发起查询无法正常返回结果 #3811

Closed AllForLandlord closed 8 months ago

AllForLandlord commented 8 months ago

Verify Steps

OpenClash Version

v0.46.003-beta

Bug on Environment

Immortalwrt

OpenWrt Version

ImmortalWrt 23.05.1 r27304-31bc47589e

Bug on Platform

Linux-arm64

Describe the Bug

详见:https://www.v2ex.com/t/1024280 223.5.5.5在进行UDP DNS查询返回A记录过多超过512字节后会重新用TCP进行DNS查询,而在开启openclash(nameserver只用223.5.5.5)的情况下无法正常进行DNS查询。复现网址:www.ai2moe.org。 表现结果为chrome浏览器访问该网站报错DNS_PROBE_FINISHED_NXDOMAIN

而关掉openclash用命令dig +tcp @223.5.5.5 -p 53 www.ai2moe.org返回结果正常。后在PC上手动设置DNS用223.5.5.5,可以正常访问www.ai2moe.org。而开了openclash就无法正常访问。

所以我推测可能openclash或者可能是meta内核对于这种情况的DNS查询有bug。

To Reproduce

openclash用meta内核,在redir-host模式下,DNS设置中启用自定义上游 DNS 服务器,nameserver只勾选223.5.5.5,fallback关掉。 访问www.ai2moe.org,发现无法访问,chrome浏览器报错DNS_PROBE_FINISHED_NXDOMAIN

OpenClash Log

OpenClash 调试日志

生成时间: 2024-03-17 11:15:30
插件版本: 
隐私提示: 上传此日志前请注意检查、屏蔽公网IP、节点、密码等相关敏感信息

#===================== 系统信息 =====================#

主机型号: FriendlyElec NanoPi R2S
固件版本: ImmortalWrt 23.05.1 r27304-31bc47589e
LuCI版本: 
内核版本: 5.15.137
处理器架构: 

#此项有值时,如不使用IPv6,建议到网络-接口-lan的设置中禁用IPV6的DHCP
IPV6-DHCP: 

DNS劫持: Dnsmasq 转发
#DNS劫持为Dnsmasq时,此项结果应仅有配置文件的DNS监听地址
Dnsmasq转发设置: 127.0.0.1#7874

#===================== 依赖检查 =====================#

dnsmasq-full: 已安装
coreutils: 已安装
coreutils-nohup: 已安装
bash: 已安装
curl: 已安装
ca-certificates: 已安装
ipset: 已安装
ip-full: 已安装
libcap: 已安装
libcap-bin: 已安装
ruby: 已安装
ruby-yaml: 已安装
ruby-psych: 已安装
ruby-pstore: 已安装
kmod-tun(TUN模式): 已安装
luci-compat(Luci >= 19.07): 已安装
kmod-inet-diag(PROCESS-NAME): 已安装
unzip: 已安装
kmod-nft-tproxy: 已安装

#===================== 内核检查 =====================#

运行状态: 运行中
运行内核:Meta
进程pid: 11681
运行权限: 11681: cap_dac_override,cap_net_bind_service,cap_net_admin,cap_net_raw,cap_sys_ptrace,cap_sys_resource=eip
运行用户: nobody
已选择的架构: linux-arm64

#下方无法显示内核版本号时请确认您的内核版本是否正确或者有无权限
Tun内核版本: 2023.08.17-13-gdcc8d87
Tun内核文件: 存在
Tun内核运行权限: 正常

Dev内核版本: v1.18.0-13-gd034a40
Dev内核文件: 存在
Dev内核运行权限: 正常

Meta内核版本: alpha-gfeedc9e
Meta内核文件: 存在
Meta内核运行权限: 正常

#===================== 插件设置 =====================#

当前配置文件: /etc/openclash/config/xxxxx.yaml
启动配置文件: /etc/openclash/xxxxx.yaml
运行模式: redir-host
默认代理模式: rule
UDP流量转发(tproxy): 停用
自定义DNS: 启用
IPV6代理: 停用
IPV6-DNS解析: 停用
禁用Dnsmasq缓存: 启用
自定义规则: 启用
仅允许内网: 启用
仅代理命中规则流量: 停用
仅允许常用端口流量: 停用
绕过中国大陆IP: 停用
路由本机代理: 启用

#启动异常时建议关闭此项后重试
混合节点: 停用
保留配置: 停用

#启动异常时建议关闭此项后重试
第三方规则: 停用

#===================== 自定义规则 一 =====================#
script:
##  shortcuts:
##    Notice: The core timezone is UTC
##    CST 20:00-24:00 = time.now().hour > 12 and time.now().hour < 16
##    内核时区为UTC,故以下time.now()函数的取值需要根据本地时区进行转换
##    北京时间(CST) 20:00-24:00 = time.now().hour > 12 and time.now().hour < 16
##    quic: network == 'udp' and dst_port == 443 and (geoip(resolve_ip(host)) != 'CN' or geoip(dst_ip) != 'CN')
##    time-limit: in_cidr(src_ip,'192.168.1.2/32') and time.now().hour < 20 or time.now().hour > 21
##    time-limit: src_ip == '192.168.1.2' and time.now().hour < 20 or time.now().hour > 21

##  code: |
##    def main(ctx, metadata):
##        directkeywordlist = ["baidu"]
##        for directkeyword in directkeywordlist:
##          if directkeyword in metadata["host"]:
##            ctx.log('[Script] matched keyword %s use direct' % directkeyword)
##            return "DIRECT"

rules:
##- SCRIPT,quic,REJECT #shortcuts rule
##- SCRIPT,time-limit,REJECT #shortcuts rule

##- PROCESS-NAME,curl,DIRECT #匹配路由自身进程(curl直连)
##- DOMAIN-SUFFIX,google.com,Proxy #匹配域名后缀(交由Proxy代理服务器组)
##- DOMAIN-KEYWORD,google,Proxy #匹配域名关键字(交由Proxy代理服务器组)
##- DOMAIN,google.com,Proxy #匹配域名(交由Proxy代理服务器组)
##- DOMAIN-SUFFIX,ad.com,REJECT #匹配域名后缀(拒绝)
##- IP-CIDR,127.0.0.0/8,DIRECT #匹配数据目标IP(直连)
##- SRC-IP-CIDR,192.168.1.201/32,DIRECT #匹配数据发起IP(直连)
##- DST-PORT,80,DIRECT #匹配数据目标端口(直连)
##- SRC-PORT,7777,DIRECT #匹配数据源端口(直连)
- IP-CIDR,103.21.244.118/32,DIRECT

##排序在上的规则优先生效,如添加(去除规则前的#号):
##IP段:192.168.1.2-192.168.1.200 直连
##- SRC-IP-CIDR,192.168.1.2/31,DIRECT
##- SRC-IP-CIDR,192.168.1.4/30,DIRECT
##- SRC-IP-CIDR,192.168.1.8/29,DIRECT
##- SRC-IP-CIDR,192.168.1.16/28,DIRECT
##- SRC-IP-CIDR,192.168.1.32/27,DIRECT
##- SRC-IP-CIDR,192.168.1.64/26,DIRECT
##- SRC-IP-CIDR,192.168.1.128/26,DIRECT
##- SRC-IP-CIDR,192.168.1.192/29,DIRECT
##- SRC-IP-CIDR,192.168.1.200/32,DIRECT

##IP段:192.168.1.202-192.168.1.255 直连
##- SRC-IP-CIDR,192.168.1.202/31,DIRECT
##- SRC-IP-CIDR,192.168.1.204/30,DIRECT
##- SRC-IP-CIDR,192.168.1.208/28,DIRECT
##- SRC-IP-CIDR,192.168.1.224/27,DIRECT

##此时IP为192.168.1.1和192.168.1.201的客户端流量走代理(策略),其余客户端不走代理
##因为Fake-IP模式下,IP地址为192.168.1.1的路由器自身流量可走代理(策略),所以需要排除

##仅设置路由器自身直连:
##- SRC-IP-CIDR,192.168.1.1/32,DIRECT
##- SRC-IP-CIDR,198.18.0.1/32,DIRECT

##DDNS
##- DOMAIN-SUFFIX,checkip.dyndns.org,DIRECT
##- DOMAIN-SUFFIX,checkipv6.dyndns.org,DIRECT
##- DOMAIN-SUFFIX,checkip.synology.com,DIRECT
##- DOMAIN-SUFFIX,ifconfig.co,DIRECT
##- DOMAIN-SUFFIX,api.myip.com,DIRECT
##- DOMAIN-SUFFIX,ip-api.com,DIRECT
##- DOMAIN-SUFFIX,ipapi.co,DIRECT
##- DOMAIN-SUFFIX,ip6.seeip.org,DIRECT
##- DOMAIN-SUFFIX,members.3322.org,DIRECT

##在线IP段转CIDR地址:http://ip2cidr.com
#===================== 自定义规则 二 =====================#
script:
##  shortcuts:
##    common_port: dst_port not in [21, 22, 23, 53, 80, 123, 143, 194, 443, 465, 587, 853, 993, 995, 998, 2052, 2053, 2082, 2083, 2086, 2095, 2096, 5222, 5228, 5229, 5230, 8080, 8443, 8880, 8888, 8889]

##  code: |
##    def main(ctx, metadata):
##        directkeywordlist = ["baidu"]
##        for directkeyword in directkeywordlist:
##          if directkeyword in metadata["host"]:
##            ctx.log('[Script] matched keyword %s use direct' % directkeyword)
##            return "DIRECT"

rules:
##- SCRIPT,common_port,DIRECT #shortcuts rule

##- DOMAIN-SUFFIX,google.com,Proxy #匹配域名后缀(交由Proxy代理服务器组)
##- DOMAIN-KEYWORD,google,Proxy #匹配域名关键字(交由Proxy代理服务器组)
##- DOMAIN,google.com,Proxy #匹配域名(交由Proxy代理服务器组)
##- DOMAIN-SUFFIX,ad.com,REJECT #匹配域名后缀(拒绝)
##- IP-CIDR,127.0.0.0/8,DIRECT #匹配数据目标IP(直连)
##- SRC-IP-CIDR,192.168.1.201/32,DIRECT #匹配数据发起IP(直连)
##- DST-PORT,80,DIRECT #匹配数据目标端口(直连)
##- SRC-PORT,7777,DIRECT #匹配数据源端口(直连)

#===================== 配置文件 =====================#

port: 7890
socks-port: 7891
allow-lan: true
mode: rule
log-level: error
external-controller: 0.0.0.0:9090
proxy-groups:
rules:
redir-port: 7892
tproxy-port: 7895
mixed-port: 7893
bind-address: "*"
external-ui: "/usr/share/openclash/ui"
ipv6: false
tcp-concurrent: true
unified-delay: true
dns:
  enable: true
  ipv6: false
  enhanced-mode: redir-host
  listen: 0.0.0.0:7874
  nameserver:
  - 223.5.5.5
  default-nameserver:
  - 223.5.5.5
  - 119.29.29.29
  use-hosts: true
profile:
  store-selected: true
authentication:
- Clash:b0HtCQ13

#===================== 自定义覆写设置 =====================#

#!/bin/sh
. /usr/share/openclash/ruby.sh
. /usr/share/openclash/log.sh
. /lib/functions.sh

# This script is called by /etc/init.d/openclash
# Add your custom overwrite scripts here, they will be take effict after the OpenClash own srcipts

LOG_OUT "Tip: Start Running Custom Overwrite Scripts..."
LOGTIME=$(echo $(date "+%Y-%m-%d %H:%M:%S"))
LOG_FILE="/tmp/openclash.log"
CONFIG_FILE="$1" #config path

#Simple Demo:
    #General Demo
    #1--config path
    #2--key name
    #3--value
    #ruby_edit "$CONFIG_FILE" "['redir-port']" "7892"
    #ruby_edit "$CONFIG_FILE" "['secret']" "123456"
    #ruby_edit "$CONFIG_FILE" "['dns']['enable']" "true"

    #Hash Demo
    #1--config path
    #2--key name
    #3--hash type value
    #ruby_edit "$CONFIG_FILE" "['experimental']" "{'sniff-tls-sni'=>true}"
    #ruby_edit "$CONFIG_FILE" "['sniffer']" "{'sniffing'=>['tls','http']}"

    #Array Demo:
    #1--config path
    #2--key name
    #3--position(start from 0, end with -1)
    #4--value
    #ruby_arr_insert "$CONFIG_FILE" "['dns']['nameserver']" "0" "114.114.114.114"

    #Array Add From Yaml File Demo:
    #1--config path
    #2--key name
    #3--position(start from 0, end with -1)
    #4--value file path
    #5--value key name in #4 file
    #ruby_arr_add_file "$CONFIG_FILE" "['dns']['fallback-filter']['ipcidr']" "0" "/etc/openclash/custom/openclash_custom_fallback_filter.yaml" "['fallback-filter']['ipcidr']"

#Ruby Script Demo:
    #ruby -ryaml -rYAML -I "/usr/share/openclash" -E UTF-8 -e "
    #   begin
    #      Value = YAML.load_file('$CONFIG_FILE');
    #   rescue Exception => e
    #      puts '${LOGTIME} Error: Load File Failed,【' + e.message + '】';
    #   end;

        #General
    #   begin
    #   Thread.new{
    #      Value['redir-port']=7892;
    #      Value['tproxy-port']=7895;
    #      Value['port']=7890;
    #      Value['socks-port']=7891;
    #      Value['mixed-port']=7893;
    #   }.join;

    #   rescue Exception => e
    #      puts '${LOGTIME} Error: Set General Failed,【' + e.message + '】';
    #   ensure
    #      File.open('$CONFIG_FILE','w') {|f| YAML.dump(Value, f)};
    #   end" 2>/dev/null >> $LOG_FILE

exit 0
#===================== 自定义防火墙设置 =====================#

#!/bin/sh
. /usr/share/openclash/log.sh
. /lib/functions.sh

# This script is called by /etc/init.d/openclash
# Add your custom firewall rules here, they will be added after the end of the OpenClash iptables rules

LOG_OUT "Tip: Start Add Custom Firewall Rules..."

exit 0
#===================== IPTABLES 防火墙设置 =====================#

#IPv4 NAT chain

#IPv4 Mangle chain

#IPv4 Filter chain

#IPv6 NAT chain

#IPv6 Mangle chain

#IPv6 Filter chain

#===================== NFTABLES 防火墙设置 =====================#

table inet fw4 {
    chain input {
        type filter hook input priority filter; policy drop;
        udp dport 443 ip daddr != @china_ip_route counter packets 0 bytes 0 reject with icmp port-unreachable comment "OpenClash QUIC REJECT"
        iifname "pppoe-wan" ip saddr != @localnetwork counter packets 22169 bytes 15231042 jump openclash_wan_input
        iifname "lo" accept comment "!fw4: Accept traffic from loopback"
        ct state established,related accept comment "!fw4: Allow inbound established and related flows"
        tcp flags syn / fin,syn,rst,ack jump syn_flood comment "!fw4: Rate limit TCP syn packets"
        iifname "eth0" jump input_lan comment "!fw4: Handle lan IPv4/IPv6 input traffic"
        iifname "pppoe-wan" jump input_wan comment "!fw4: Handle wan IPv4/IPv6 input traffic"
        jump handle_reject
    }
}
table inet fw4 {
    chain forward {
        type filter hook forward priority filter; policy drop;
        ct state established,related accept comment "!fw4: Allow forwarded established and related flows"
        iifname "eth0" jump forward_lan comment "!fw4: Handle lan IPv4/IPv6 forward traffic"
        iifname "pppoe-wan" jump forward_wan comment "!fw4: Handle wan IPv4/IPv6 forward traffic"
        jump handle_reject
    }
}
table inet fw4 {
    chain dstnat {
        type nat hook prerouting priority dstnat; policy accept;
        ip daddr { 8.8.4.4, 8.8.8.8 } tcp dport 53 counter packets 0 bytes 0 redirect to :7892 comment "OpenClash Google DNS Hijack"
        udp dport 53 ip saddr != @lan_ac_black_ips counter packets 2 bytes 122 redirect to :53 comment "OpenClash DNS Hijack"
        tcp dport 53 ip saddr != @lan_ac_black_ips counter packets 0 bytes 0 redirect to :53 comment "OpenClash DNS Hijack"
        iifname "pppoe-wan" jump dstnat_wan comment "!fw4: Handle wan IPv4/IPv6 dstnat traffic"
        ip protocol tcp counter packets 755 bytes 40035 jump openclash
    }
}
table inet fw4 {
    chain srcnat {
        type nat hook postrouting priority srcnat; policy accept;
        oifname "pppoe-wan" jump srcnat_wan comment "!fw4: Handle wan IPv4/IPv6 srcnat traffic"
    }
}
table inet fw4 {
    chain nat_output {
        type nat hook output priority filter - 1; policy accept;
        ip protocol tcp counter packets 2307 bytes 143084 jump openclash_output
    }
}
table inet fw4 {
    chain mangle_prerouting {
        type filter hook prerouting priority mangle; policy accept;
    }
}
table inet fw4 {
    chain mangle_output {
        type route hook output priority mangle; policy accept;
    }
}
table inet fw4 {
    chain openclash {
        ip daddr @localnetwork counter packets 38 bytes 2123 return
        ip saddr @lan_ac_black_ips counter packets 0 bytes 0 return
        ip protocol tcp counter packets 717 bytes 37912 redirect to :7892
    }
}
table inet fw4 {
    chain openclash_output {
        ip daddr @localnetwork counter packets 509 bytes 35204 return
        ip protocol tcp meta skuid != 65534 counter packets 4 bytes 240 redirect to :7892
    }
}
table inet fw4 {
    chain openclash_wan_input {
        udp dport { 7874, 7890, 7891, 7892, 7893, 7895, 9090 } counter packets 0 bytes 0 reject
        tcp dport { 7874, 7890, 7891, 7892, 7893, 7895, 9090 } counter packets 0 bytes 0 reject
    }
}

#===================== IPSET状态 =====================#

#===================== 路由表状态 =====================#

#IPv4

#route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         100.79.128.1    0.0.0.0         UG    0      0        0 pppoe-wan
10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
100.79.128.1    0.0.0.0         255.255.255.255 UH    0      0        0 pppoe-wan

#ip route list
default via 100.79.128.1 dev pppoe-wan proto static 
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.1 
100.79.128.1 dev pppoe-wan proto kernel scope link src *WAN IP*.124 

#ip rule show
0:  from all lookup local
32766:  from all lookup main
32767:  from all lookup default

#IPv6

#route -A inet6
Kernel IPv6 routing table
Destination                                 Next Hop                                Flags Metric Ref    Use Iface
fe80::76e9:bfff:fe68:2049/128               ::                                      U     256    1        0 pppoe-wan
fe80::a465:d707:2c63:7b03/128               ::                                      U     256    1        0 pppoe-wan
fe80::/64                                   ::                                      U     256    1        0 eth1    
fe80::/64                                   ::                                      U     256    1        0 eth0    
::/0                                        ::                                      !n    -1     1        0 lo      
::1/128                                     ::                                      Un    0      6        0 lo      
fe80::/128                                  ::                                      Un    0      3        0 eth1    
fe80::/128                                  ::                                      Un    0      3        0 eth0    
fe80::a465:d707:2c63:7b03/128               ::                                      Un    0      2        0 pppoe-wan
fe80::ac70:b7ff:feda:38f5/128               ::                                      Un    0      2        0 eth0    
fe80::ac70:b7ff:feda:38f6/128               ::                                      Un    0      5        0 eth1    
ff00::/8                                    ::                                      U     256    3        0 eth1    
ff00::/8                                    ::                                      U     256    2        0 eth0    
ff00::/8                                    ::                                      U     256    2        0 pppoe-wan
::/0                                        ::                                      !n    -1     1        0 lo      

#ip -6 route list
fe80::76e9:bfff:fe68:2049 dev pppoe-wan proto kernel metric 256 pref medium
fe80::a465:d707:2c63:7b03 dev pppoe-wan proto kernel metric 256 pref medium
fe80::/64 dev eth1 proto kernel metric 256 pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium

#ip -6 rule show
0:  from all lookup local
32766:  from all lookup main

#===================== 端口占用状态 =====================#

tcp        0      0 :::7890                 :::*                    LISTEN      11681/clash
tcp        0      0 :::7891                 :::*                    LISTEN      11681/clash
tcp        0      0 :::7892                 :::*                    LISTEN      11681/clash
tcp        0      0 :::7893                 :::*                    LISTEN      11681/clash
tcp        0      0 :::7895                 :::*                    LISTEN      11681/clash
tcp        0      0 :::9090                 :::*                    LISTEN      11681/clash
udp        0      0 :::7874                 :::*                                11681/clash
udp        0      0 :::7891                 :::*                                11681/clash
udp        0      0 :::7892                 :::*                                11681/clash
udp        0      0 :::7893                 :::*                                11681/clash
udp        0      0 :::7895                 :::*                                11681/clash

#===================== 测试本机DNS查询(www.baidu.com) =====================#

Server:     127.0.0.1
Address:    127.0.0.1:53

www.baidu.com   canonical name = www.a.shifen.com
Name:   www.a.shifen.com
Address: 153.3.238.110
Name:   www.a.shifen.com
Address: 153.3.238.102

#===================== 测试内核DNS查询(www.instagram.com) =====================#

Status: 0
TC: false
RD: true
RA: true
AD: false
CD: false

Question: 
  Name: www.instagram.com.
  Qtype: 1
  Qclass: 1

Answer: 
  TTL: 180
  data: 162.125.32.9
  name: www.instagram.com.
  type: 1

Dnsmasq 当前默认 resolv 文件:/tmp/resolv.conf.d/resolv.conf.auto

#===================== /tmp/resolv.conf.auto =====================#

# Interface lan
nameserver 119.29.29.29
nameserver 8.8.8.8

#===================== /tmp/resolv.conf.d/resolv.conf.auto =====================#

# Interface lan
nameserver 119.29.29.29
nameserver 8.8.8.8

#===================== 测试本机网络连接(www.baidu.com) =====================#

HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
Connection: keep-alive
Content-Length: 277
Content-Type: text/html
Date: Sun, 17 Mar 2024 03:15:37 GMT
Etag: "575e1f60-115"
Last-Modified: Mon, 13 Jun 2016 02:50:08 GMT
Pragma: no-cache
Server: bfe/1.0.8.18

#===================== 测试本机网络下载(raw.githubusercontent.com) =====================#

HTTP/2 404 
content-security-policy: default-src 'none'; style-src 'unsafe-inline'; sandbox
strict-transport-security: max-age=31536000
x-content-type-options: nosniff
x-frame-options: deny
x-xss-protection: 1; mode=block
content-type: text/plain; charset=utf-8
x-github-request-id: 4DAC:2F042B:20F398:24FE97:65F66059
accept-ranges: bytes
date: Sun, 17 Mar 2024 03:15:38 GMT
via: 1.1 varnish
x-served-by: cache-nrt-rjtf7700028-NRT
x-cache: MISS
x-cache-hits: 0
x-timer: S1710645338.948725,VS0,VE249
vary: Authorization,Accept-Encoding,Origin
access-control-allow-origin: *
cross-origin-resource-policy: cross-origin
x-fastly-request-id: a942782b0ea49c4240b41ee740cbd9ca32a10895
expires: Sun, 17 Mar 2024 03:20:38 GMT
source-age: 0
content-length: 14

OpenClash Config

dns:
  enable: true
  ipv6: false
  enhanced-mode: redir-host
  listen: 0.0.0.0:7874
  nameserver:
  - 223.5.5.5
  default-nameserver:
  - 223.5.5.5
  - 119.29.29.29
  use-hosts: true

Expected Behavior

openclash用meta内核,在redir-host模式下,nameserver只勾选223.5.5.5时能正常访问www.ai2moe.org不报错。

Additional Context

No response

AllForLandlord commented 8 months ago

刚才把所有都更新到最新的dev版本了,meta alpha-gb3db113,debug信息如下:

DNS
vernesong commented 8 months ago

内核的问题

AllForLandlord commented 8 months ago

内核的问题

好的,我去向meta内核反馈下这个问题,谢谢V大