跳转至

白名单分流请求

分流流程

分流需要实现的功能如下:

  • 内部域名从内部DNS服务器查询,并对IP进行测速,将最快IP地址返回客户端。
  • 外部域名从外部服务器查询,外部域名通过域名列表管理,IP数据通过TPROXY进行透明转发。

对应的流程图如下:

%%{init: {'theme':'forest'}}%%
flowchart 
    style client color:white,fill:#dd5555,stroke:#ee00,stroke-width:2px
    style ipset color:white,fill:green,stroke:#ee00,stroke-width:2px
    style ipset1 color:white,fill:green,stroke:#ee00,stroke-width:2px
    style speed-check color:white,fill:green,stroke:#ee00,stroke-width:2px
    client(((客户端)))-----> |1. 请求|smartdns
    smartdns---->|2. 获取到IP|client
    client--->|3. 使用IP请求数据|router
    subgraph smartdns [SmartDNS&nbsp&nbsp]
        server(DNS服务)-->|a. 处理规则namserver|rule(域名规则)
        rule-->|b. 外部域名|public-group(外部服务器组)
        rule-->|b. 内部域名|private-group(内部服务器组)
        public-group-->|d. IP加入IPSet|ipset1(IPSet,NFTSet)
        private-group-->|d. 测速获取最快IP|speed-check(测速)
    end
    router-->ipset(IPSet,NFTSet)
    subgraph router [路由网关]
        NAT-->|a. 收取数据包|ipset-->|b. 数据转发|tproxy(TPROXY转发服务)
    end
    tproxy----->|VPN|ProxyServer
    tproxy----->|SOCKS5|ProxyServer
    tproxy----->|HTTP PROXY|ProxyServer

    public-group--->|c. 查询外部域名|public-servers(外部DNS服务器)
    private-group--->|c. 查询内部域名|private-servers(内部DNS服务器)
  1. 客户端到SmartDNS服务器查询域名。
  2. SmartDNS处理请求。
    1. 根据namserver给定的规则判断域名
    2. 如果域名为内部域名,则使用内部域名服务器查询;如果域名为外部域名,则使用外部域名服务器查询。
      1. 内部域名,使用测速功能,获取最快IP地址。
      2. 外部域名,获取最快响应DNS结果后,将IP地址添加到IPSet/NFTSet中。
    3. SmartDNS返回IP地址。
  3. 客户端从SmartDNS获取到IP地址。
  4. 客户端使用IP地址通过网关请求数据。
  5. 网关接受到数据包,使用IPSet/NFTSet判断IP规则。
    1. 如果IP存在IPSet/NFTSet中(外部域名),则使用TPROXY将数据发送到远端代理服务器。
    2. 如果IP不存在IPSet/NFTSet中(内部域名),则直接NAT转发数据。

SmartDNS分流配置

  1. 在上述流程图中,SmartDNS分流数据,需要做如下设置

    • 内部域名从内部DNS服务器查询,并对IP进行测速,将最快IP地址返回客户端。
    • 外部域名从外部服务器查询,不进行测速,将IP地址放入IPSet/NFTSet中供数据转发。
  2. 基本配置

    启用SmartDNS服务,并设置相关的功能。

    # 启用服务器
    bind [::]:53
    # 启用测速
    speed-check-mode ping,tcp:80,tcp:443
    # 启用双栈优选
    dualstack-ip-selection yes
    # 启用缓存和持久化
    cache-size 32768
    cache-persist yes
    prefetch-domain yes
    serve-expired yes
    
  3. 添加DNS服务器

    添加上游服务器,并通过-group参数指定内外服务器组。

    # 外部服务器组
    server 1.2.3.4 -group public
    
    # 内部服务器组
    server 1.2.3.4 -group private
    

    注意:

    1. 推荐配置多个外部和内部服务器。
    2. public外部服务器组,可选择配置-exclude-default-group参数,避免内部域名通过外部服务器查询。
    3. public外部服务器组,可以使用proxy-server选项,配置通过socks5,http代理查询,这样结果会更好。
  4. 配置域名规则

    配置白名单域名,对名单中的域名走public服务器组,并关闭测速,关闭IPV6,加入IPSET。

    # 添加域名列表,格式为一行一个域名
    domain-set -name public-domain-list -file /path/to/public/domain/list
    # 设置对应域名列表的规则。
    domain-rules /domain-set:public-domain-list/ -ipset public  -nftset #4:ip#table#set -c none -address #6 -nameserver public
    

    注意:

    1. 域名列表可以配置crontab周期自动更新,其格式为一行一个域名。

      a.com
      b.com
      ...
      
    2. 域名规则中:

      1. -ipset: 表示添加结果到对应的ipset名称,public为例子,可按需修改为对应的ipset名称。
      2. -nftset: 表示添加结果到对应的nftset名称,#4:ip#table#set为例子,需要修改为对应的ipset名称。
      3. -c none: 表示禁用测速,具体参数参考speed-check-mode。
      4. -address #6: 表示禁用IPV6,如果转发程序支持IPV6,则可以不使用此参数。
      5. -nameserver public: 表示使用public组的DNS服务器解析结果。

IPSET以及透明转发规则配置

为配合smartdns完成外部请求的转发,好需要配置相关的ipset,和规则。具体配置步骤如下:

  1. 创建IPSet

    执行shell命令,创建IPSET。

    # 创建ipset集合
    ipset create public hash:net
    
  2. SmartDNS中配置规则

    ipset /example.com/public
    
  3. 设置透明转发规则:

    Linux透明转发分为TPROXY和REDIRECT两种模式,这两种模式使用上有如下区别,可按需求选择配置。

    模式:TPROXY,REDIRECT

    TPROXY:支持UDP,TCP的转发,配置稍复杂。
    REDIRECT:仅支持TCP,配置简单。

    1. 方式一:仅TCP转发(容易)

      • 设置规则

        # 设置转发规则,将匹配的请求转发到本机的1081端口
        iptables -t nat -I PREROUTING -p tcp -m set --match-set public dst -j REDIRECT --to-ports 1081
        
      • 启用转发程序

        本机1081端口开启REDIRECT模式的转发程序。

      • 删除规则:

        iptables -t nat -D PREROUTING -p tcp -m set --match-set public dst -j REDIRECT --to-ports 1081
        
    2. 方式二:TCP/UDP TPROXY转发

      执行shell命令,设置iptable规则,将匹配的域名TCP/UDP请求进行TPROXY方式透明转发,规则参考如下:

      • 设置规则

        # 设置路由规则
        ip rule add fwmark 1104 lookup 1104
        ip route add local 0.0.0.0/0 dev lo table 1104
        
        # 设置转发规则,UDP,TCP方式的TPROXY转发,将数据转发到本机的1081端口
        iptables -t mangle -N SMARTDNS
        iptables -t mangle -A SMARTDNS -p tcp -m set --match-set public dst -j TPROXY --on-ip 127.0.0.1 --on-port 1081 --tproxy-mark 1104
        iptables -t mangle -A SMARTDNS -p udp -m set --match-set public dst -j TPROXY --on-ip 127.0.0.1 --on-port 1081 --tproxy-mark 1104
        iptables -t mangle -A SMARTDNS -j ACCEPT
        iptables -t mangle -A PREROUTING -j SMARTDNS
        
      • 启用转发程序

        本机1081端口开启TPROXY模式的转发程序。

      • 删除规则:

        ip rule del fwmark 1104
        iptables -t mangle -D PREROUTING -j SMARTDNS
        iptables -t mangle -F SMARTDNS
        iptables -t mangle -X SMARTDNS
        

NFTSET以及透明转发规则配置

  1. 方式一:仅TCP转发 (容易)

    1. 创建nftable的nftset集合,集合名称为#4:ip#nat#public_set

      nft add set ip nat public_set { type ipv4_addr\; flags interval\; auto-merge\; }
      
    2. 设置REDIRECT转发规则

      nft add rule ip nat PREROUTING meta l4proto tcp ip daddr @public_set redirect to :1081
      
    3. smartdns中配置nftable规则

      nftset /example.com/#4:ip#nat#public_set
      
    4. 启用转发程序

      本机1081端口开启REDIRECT模式的转发程序。

    5. 注意可以单独创建一张转发表,方便管理,如下,创建smartdns表,nftset名称为#4:ip#smartdns#public

      # 创建smartdns表
      nft add table ip smartdns
      # 创建NFTSET集合
      nft add set ip smartdns public { type ipv4_addr\; flags interval\; auto-merge\; }
      # 设置转发规则
      nft add chain ip smartdns prerouting { type nat hook prerouting priority dstnat + 1\; }
      nft add rule ip smartdns prerouting meta l4proto tcp ip daddr @public redirect to :1081
      
      # 删除表格
      nft delete table ip smartdns
      
  2. 方式二:TPROXY模式转发TCP和UDP

    1. 配置规则

      # 设置路由规则
      ip rule add fwmark 1104 lookup 1104
      ip route add local 0.0.0.0/0 dev lo table 1104
      
      # 创建smartdns表
      nft add table ip smartdns
      # 创建NFTSET集合
      nft add set ip smartdns public { type ipv4_addr\; flags interval\; auto-merge\; }
      # 设置转发规则
      nft add chain ip smartdns prerouting { type filter hook prerouting priority 0\; }
      nft add rule ip smartdns prerouting meta l4proto tcp ip daddr @public tproxy to :1081 mark set 1104
      nft add rule ip smartdns prerouting meta l4proto udp ip daddr @public tproxy to :1081 mark set 1104
      
      # 查询规则
      nft list table ip smartdns
      
      # 删除已有规则
      nft delete table ip smartdns
      
    2. smartdns配置nftset

      nftset /example.com/#4:ip#smartdns#public
      
    3. 启用转发程序

      本机1081端口开启TPROXY模式的转发程序。

额外说明

如果使用OpenWrt的luci界面,可以直接在界面配置相关的域名分流规则。