V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yamada
V2EX  ›  Android

ANDROID 通过 IPTABLES 转发 UDP DNS,会绕到路由

  •  1
     
  •   yamada · 2016-01-13 22:23:05 +08:00 · 10059 次点击
    这是一个创建于 3232 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在 android 上,我为了避免 DNS 污染,打算自己解析 DNS ,
    使用 iptables -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination 127.0.0.1:XXX ,然后程序监听本地的 XXX 端口用来处理这个 DNS 请求,但是我发现 DNS 请求会先绕到网关,然后在发回手机给我的监听,接收到 UDP DNS 请求后发现远程地址也是本机的内网 IP ,而不是 127.0.0.1 ,这在我自己家里的 WIFI 没问题,但在一些公共 WIFI 或 3G\4G 的情况下,有些网关有 DNS 缓存,会直接返回结果而不会再发送给我解析,我在本地的监听根本没有收到请求,导致一些网站 DNS 解析不正确。
    我参考了 SS 后发现它也是这么做的,那它怎么处理这个问题的?

    第 1 条附言  ·  2016-01-14 00:04:48 +08:00
    在说明一下问题:
    我在本地监听 XXX 端口处理 DNS 请求,并且添加了一条规则: iptables -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination 127.0.0.1:XXX
    问题是有时候能收到 DNS 请求,有时候收不到。

    能收到 DNS 的请求是在家里的 WIFI 和公司的 WIFI ,很稳定,接收到请求时远程 ip 为本机的内网 IP ,而不是 127.0.0.1 。
    时而收的到时而收不到 DNS 的请求是在公共 WIFI 或 4G\3G 下,收不到 DNS 请求但域名却能解析成功。

    所以现在怀疑是不是 DNS 请求会先发到网关然后再发回手机进行解析? 有时候收不到 DNS 请求可能是网关有 DNS 缓存直接返回了 DNS 查询结果而没有再发回手机?不然的话又要怎么解释收到请求时远程 IP 不是 127.0.0.1 而是内网 IP ?我有开关飞行模式清理 DNS 缓存。
    12 条回复    2016-01-14 13:15:33 +08:00
    squid157
        1
    squid157  
       2016-01-13 22:35:12 +08:00 via iPhone
    表不对 手机上不用 nat 表
    acess
        2
    acess  
       2016-01-13 22:40:35 +08:00
    ss 我不知道是怎么处理的,但我记得与 Android 的 ndc 命令有关系。 Android 有自己的 DNS 缓存。
    yamada
        3
    yamada  
    OP
       2016-01-13 22:57:50 +08:00
    @squid157 看过了 SS 的源码,一样是 nat 没错的,转 80 和 443 什么的没问题,连接时的远程 ip 也是 127.0.0.1
    miclushine
        4
    miclushine  
       2016-01-13 23:15:48 +08:00
    安卓上 wifi 和移动数据用的不同的 dns ,每个进程都有单独的 dns 缓存。 4.3 以上的 android 如果没有魔改过 dns 部分,彻底手动改 dns 解析基本无解。
    yamada
        5
    yamada  
    OP
       2016-01-13 23:44:07 +08:00
    @miclushine DNS 缓存我通过开关一次飞行模式还是能够清掉的, 4G 下在有的地方本地监听能收到 DNS 请求,而在有的地方则收不到,但是这个域名却解析成功了,所以怀疑是网关有 DNS 缓存直接返回了解析结果
    yamada
        6
    yamada  
    OP
       2016-01-13 23:47:13 +08:00
    总结一下现在的问题就是:为什么添加了 iptables , DNS 请求会先绕到网关然后在发回手机进行解析?而不是直接在本地解析?我都已经-j DNAT --to-destination 127.0.0.1:XXX 了, 80 和 443 之类的则没问题是直接就在本机被处理了
    tatsuteng
        7
    tatsuteng  
       2016-01-14 09:07:14 +08:00 via Android
    DNAT 不会改变源地址,所以看起源地址是内网 IP
    yamada
        8
    yamada  
    OP
       2016-01-14 10:40:32 +08:00 via Android
    @tatsuteng 我知道,但为什么是内网 ip 而不是 127 ?是不是说明这个 udp dns 包先绕到了网关再回到手机?
    yamada
        9
    yamada  
    OP
       2016-01-14 10:58:35 +08:00 via Android
    我做了一个这样的测试:断开 wifi ,关闭流量, ping 域名,直接显示 unknow ,并且我的监听程序没有接收到 dns udp 查询包,如果 iptables 生效了的话, dns udp 应该直接被转发到了我本地 127 上吧,但是并没有,看来还是会先发到网关再转回来?怎么直接发到本地 127 ?
    tatsuteng
        10
    tatsuteng  
       2016-01-14 11:47:28 +08:00 via Android
    源地址是内网 IP 并不代表它会先绕到网关,因为内网 IP 和 127.0.0.1 都是本机的地址,所以 UDP 包会直接在内核中从 wlan0 发到 lo 。至于断开 wifi 和数据连接,手机就不知道谁是 DNS 服务器了吧,当然发不出了
    yamada
        11
    yamada  
    OP
       2016-01-14 12:46:41 +08:00
    @tatsuteng 那我的监听为什么一直收不到 DNS 请求在 3G\4G 下……是不是因为 UDP 从 IPV6 发出去了?
    tatsuteng
        12
    tatsuteng  
       2016-01-14 13:15:33 +08:00 via Android
    不清楚,去装个 tcpdump 抓包吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3480 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 11:19 · PVG 19:19 · LAX 03:19 · JFK 06:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.