0%

一些针对DNS和透明网关的更新

5年前曾写过一篇“科学”使用树莓派的教程,尽管时间比较久,现在仍然在使用教程中的核心功能和思路,说明可靠性不错。不过由于各种不可描述的原因,部分工具已经停止维护,偶尔也会出现兼容性和奇怪的问题。这次利用假期在此前思路和近几年新工具的基础上推倒重来,各种服务之间的关系更加清晰,效率和稳定性有了进一步提高。

不同于其他内容,这篇“科学”教程不能写的太细。但会争取把一些其他文章没有提到的关键内容说清楚,避免新手踩坑。

一、主要通道

  • 与vps之间的主要通道选择用trojan建立
    apt install trojan
    
  • 配置文件放在/etc/trojan/config.json,具体内容参考vps服务端生成的内容。客户端配置的cert字段不建议留空,补全fullchain证书比较稳妥
  • 由于后续采用透明网关,主要通道相关服务统一通过pi用户运行,以便区分
    chown pi /usr/bin/trojan
    chgrp pi /usr/bin/trojan
    
  • 创建/etc/systemd/system/trojan.service服务,注意After内容
    [Unit]
    Description=trojan
    Documentation=man:trojan(1) https://trojan-gfw.github.io/trojan/config https://trojan-gfw.github.io/trojan/
    After=network.target network-online.target nss-lookup.target
    #
    [Service]
    Type=simple
    StandardError=journal
    User=pi
    Group=pi
    AmbientCapabilities=CAP_NET_BIND_SERVICE
    ExecStart=/usr/bin/trojan -c /etc/trojan/config.json
    ExecReload=/bin/kill -HUP $MAINPID
    Restart=on-failure
    RestartSec=1s
    #
    [Install]
    WantedBy=multi-user.target
    

二、透明网关

原始版本的trojan提供的是socks5,默认不支持redirect或tproxy方式的透明网关。解决办法有很多,例如redsocks、v2ray、clash和glider等工具进行转换。

    1. 配置glider

  • 个人喜欢用glider转换为ss服务后再搭配ss-redir实现。主要是日常会使用ss建立一些境内通道方便使用(和openvpn一样,ss的境内通道不会受到wall的干扰)
  • https://github.com/nadoo/glider/releases中下载armv7版本
  • 主程序放在/usr/local/bin,配置文件放在/etc/glider/server.conf,同样使用chown和chgrp修改为pi。server.conf内容如下
    listen=:8443
    # 转换为ss,工作端口号529
    listen=ss://AES-256-CFB:yourpassword@:529
    # trojan的端口号527
    forward=socks5://127.0.0.1:527
    #
    verbose=True
    
  • 创建/etc/systemd/system/glider@server.service服务,After中添加trojan.service
    [Unit]
    Description=Glider Service (%i)
    After=network.target trojan.service
    #
    [Service]
    Type=simple
    User=pi
    Group=pi
    Restart=always
    LimitNOFILE=102400
    #
    # NOTE: change to your glider path
    ExecStart=/usr/local/bin/glider -config /etc/glider/%i.conf
    #
    # work with systemd v229 or later, so glider can listen on port below 1024 with none-root user
    # CAP_NET_ADMIN: ipset
    # CAP_NET_BIND_SERVICE: bind ports under 1024
    CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
    AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
    NoNewPrivileges=true
    #
    [Install]
    WantedBy=multi-user.target
    

    2. 配置ss-redir

  • 安装shadowsocks-libev
    apt install shadowsocks-libev
    
  • 因为我们需要的是ss-redir,关掉默认的shadowsocks-libev.service,并修改/usr/bin/ss-redir的拥有者和群组为pi
  • 创建/etc/systemd/system/ss-redir.service服务,After中添加glider@server.service和trojan.service
    [Unit]
    Description=SS-Redir Service
    After=network.target glider@server.service trojan.service
    #
    [Service]
    Type=simple
    User=pi
    Group=pi
    Restart=always
    LimitNOFILE=102400
    #
    # NOTE: change to your ss-redir path
    # 监听端口号为1080
    ExecStart=/usr/bin/ss-redir -s 127.0.0.1 -p 529 -b 0.0.0.0 -l 1080 -k yourpassword -m aes-256-cfb -u
    #
    CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
    AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
    NoNewPrivileges=true
    #
    [Install]
    WantedBy=multi-user.target
    
  • 通过以下命令可以查看运行是否准确
    top -u pi
    
  • 正确显示为
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
    638 pi        20   0   38640  22480   7120 S   0.0   0.6   0:31.52 trojan
    639 pi        20   0  800472  12576   3968 S   0.0   0.3   0:37.07 glider
    640 pi        20   0    4764   2812   2228 S   0.0   0.1   0:21.47 ss-redir
    

    3. 配置ipset和iptables

  • ipset中配置chnroute,用于识别线路,内容来自于chinadns-ng
    ipset -R < chnroute.ipset
    
  • 创建/etc/systemd/system/ipset.service服务实现重启后自动加载,注意ConditionFileNotEmpty和After
    [Unit]
    Description=ipset persistent rule service
    ConditionFileNotEmpty=/root/dnstools/chinadns-ng/chnroute.ipset
    After=network.target
    #
    [Service]
    Type=oneshot
    RemainAfterExit=true
    ExecStart=/sbin/ipset -exist -file /root/dnstools/chinadns-ng/chnroute.ipset restore
    #
    [Install]
    WantedBy=multi-user.target
    
  • 配置sysctl开启net.ipv4.ip_forward=1
  • iptables配置内容如下
    iptables -t nat -N SHADOWSOCKS
    iptables -t nat -A PREROUTING -p tcp -j SHADOWSOCKS
    # 排除pi用户的访问(也即trojan、glider和ss-redir),用户uid通过id username查看
    iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner 1000 -j SHADOWSOCKS
    # 排除Lan
    iptables -t nat -A SHADOWSOCKS -d 0.0.0.0/8 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 10.0.0.0/8 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 127.0.0.0/8 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 169.254.0.0/16 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 172.16.0.0/16 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 192.168.0.0/16 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 224.0.0.0/4 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 240.0.0.0/4 -j RETURN
    # 排除本机到vps的访问
    iptables -t nat -A SHADOWSOCKS -s 127.0.0.1/32 -d xxx.xxx.xxx.xxx/32 -j RETURN
    # 通过ipset中的chnroute判断国内ip
    iptables -t nat -A SHADOWSOCKS -p tcp -m set --match-set chnroute dst -j RETURN
    # 其他访问走ss-redir的1080端口(后续可信dns通过DoT和DoH实现)
    iptables -t nat -A SHADOWSOCKS -p tcp -j REDIRECT --to-ports 1080
    
  • 修改/lib/systemd/system/netfilter-persistent.service服务,在After中增加ipset.service,否则在ipset.service运行完毕之前,iptables-restore会因为找不到ipset chnroute而恢复失败
    After=systemd-modules-load.service local-fs.target ipset.service
    

三、DNS的配置

DNS要考虑的核心问题有三个:避免污染、区分线路高速解析、保证正确解析境内外地址。尤其是第三点,因为一些大厂如Google、Apple和阿里,会根据不同的DNS服务器访问IP给出不同的服务器地址,而Apple的用户认证还屏蔽了大多数vps的ip,往往造成鉴权失败。

目前使用的方案是AdGuardHome + dnsmasq (china-list) + chinadns-ng + smartdns

                                                         | Trusted Group (DoH)
AdGuardHome --> dnsmasq --> chinadns-ng --> smartdns --> | 
(AD filter)   (accelerate)  (addr match)    (fastest)    | Mainland Group (UDP)

    1. 安装smartdns

  • https://github.com/pymumu/smartdns/releases下载smartdns.xxxxxxxx.arm-debian-all.deb安装包,使用以下命令安装
    dpkg -i smartdns.xxxxxxxx.arm-debian-all.deb
    
  • 修改配置文件/etc/smartdns/smartdns.conf
  • # chn组端口号为5304
    bind [::]:5304 -group chn
    # trusted组端口号为5308
    bind [::]:5308 -group trusted
    # chn组走国内DNS,杭州走阿里的223.6.6.6比114更快
    server 223.6.6.6 -group chn -exclude-default-group
    server 114.114.114.114 -group chn -exclude-default-group
    # trusted组走DoT和DoH解析,这里采用Google和OpenDNS的
    server-tls 8.8.8.8:853 -group trusted -exclude-default-group
    server-https https://dns.google/dns-query -group trusted -exclude-default-group
    server-https https://doh.opendns.com/dns-query -group trusted -exclude-default-group
    cache-size 4096
    log-level info
    

    2. 安装chinadns-ng

  • 编译安装
    git clone https://github.com/zfl9/chinadns-ng
    cd chinadns-ng
    make && sudo make install
    
  • 创建/etc/systemd/system/chinadns-ng.service服务,After中添加smartdns.service
    [Unit]
    Description=ChinaDNS-ng Service
    After=network.target smartdns.service
    #
    [Service]
    Type=simple
    Restart=always
    #
    # 使用端口号5303
    ExecStart=/usr/local/bin/chinadns-ng -l 5303 -c 127.0.0.1#5304 -t 127.0.0.1#5308 -g /root/dnstools/chinadns-ng/gfwlist.txt -m /root/dnstools/chinadns-ng/chnlist.txt
    #
    [Install]
    WantedBy=multi-user.target
    

    3. 安装dnsmasq-china-list

  • 安装文件在https://raw.githubusercontent.com/felixonmars/dnsmasq-china-list/master/install.sh
  • 具体配置文件在/etc/dnsmasq.d/,该目录下的conf文件都会在dnsmasq启动时自动全部加载
  • 创建chinadns-ng.conf
    # 使用端口号5302
    port=5302
    no-resolv
    cache-size=1000
    # 上游指向chinadns-ng的5303
    server=127.0.0.1#5303
    clear-on-reload
    
  • 修改/lib/systemd/system/dnsmasq.service,After中添加smartdns.service和chinadns-ng.service

    4. 安装AdGuardHome

  • 下载安装
    cd $HOME
    wget https://static.adguard.com/adguardhome/release/AdGuardHome_linux_arm.tar.gz
    tar xvf AdGuardHome_linux_arm.tar.gz
    cd AdGuardHome
    ./AdGuardHome -s install
    
  • 访问http://127.0.0.1:3000/进行安装配置
  • 在DNS settings中将上游DNS服务器指向dnsmasq的5302端口
    127.0.0.1:5302
  • 修改/etc/systemd/system/AdGuardHome.service,After中添加dnsmasq.service

    5. 针对Apple的额外配置

  • 尽管dnsmasq-china-list已经针对Apple的国内服务进行了加速,例如云上贵州的存储。然而,Apple的用户鉴权服务仍然全部在美国,经过探测有以下几个域名,个人选择创建conf文件放到/etc/dnsmasq.d/
    server=/www.icloud.com/223.6.6.6
    server=/appleid.apple.com/223.6.6.6
    server=/idmsa.apple.com/223.6.6.6
    server=/appleid.cdn-apple.com/223.6.6.6
    
  • 由于vps的ip被Apple屏蔽,会导致页面正确打开,但鉴权死活fail的情况,这个问题基本上Apple商店的“天才们”也是弄不清楚的。在iptables中排除后问题解决
    iptables -t nat -A SHADOWSOCKS -d 17.137.166.0/24 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 17.141.5.0/24 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 17.151.240.0/24 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 17.253.144.0/24 -j RETURN
    iptables -t nat -A SHADOWSOCKS -d 118.214.109.0/24 -j RETURN
    

四、搭建Wireguard方便外部访问

  • 树莓派平台暂不能直接apt install wireguard,需要编译

    # 安装依赖工具
    apt install libmnl-dev git
    apt install libelf-dev build-essential pkg-config
    # 安装内核头文件(编译内核用)
    apt install raspberrypi-kernel-headers
    # 获取文件
    cd  /usr/local/src
    git clone https://git.zx2c4.com/wireguard-linux-compat
    git clone https://git.zx2c4.com/wireguard-tools
    # 编译安装module
    make -C wireguard-linux-compat/src -j$(nproc)
    make -C wireguard-linux-compat/src install
    # 编译安装wireguard
    make -C wireguard-tools/src -j$(nproc)
    make -C wireguard-tools/src install
    
  • 创建/lib/systemd/system/wg-quick@wg0.service

  • 配置文件在/etc/wireguard/wg0.conf

    [Interface]
    Address = 10.66.66.1/24,fd42:42:42::1/64
    ListenPort = 39770
    PrivateKey = server_privatekey
    PostUp = iptables -A FORWARD -i eth0 -o wg0 -j ACCEPT; iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    PostDown = iptables -D FORWARD -i eth0 -o wg0 -j ACCEPT; iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
    #
    ### Client ian-iphone
    [Peer]
    PublicKey = client1_publickey
    PresharedKey = PresharedKey
    AllowedIPs = 10.66.66.9/32,fd42:42:42::9/128
    #
    ### Client ian-p5550
    [Peer]
    PublicKey = client2_publickey
    PresharedKey = PresharedKey
    AllowedIPs = 10.66.66.8/32,fd42:42:42::8/128
    
  • 具体的key可以用以下方式获得,服务端配置文件写服务端的privatekey和客户端的publickey;客户端配置文件写服务端的publickey和客户端的privatekey

    wg genkey | tee privatekey1 | wg pubkey > publickey1
    
  • wg的PresharedKey用于两端加密混淆,建议填写使用,两端保持一致

    wg genpsk > presharedkey
    
  • 客户端配置文件举例

    [Interface]
    PrivateKey = client1_privatekey
    Address = 10.66.66.9/32,fd42:42:42::9/128
    DNS = 10.66.66.1,10.66.66.1
    #
    [Peer]
    PublicKey = server_publickey
    PresharedKey = PresharedKey
    # Use Your Server IP
    Endpoint = xxx.xxx.xxx.xxx:39770
    AllowedIPs = 0.0.0.0/0,::/0
    
  • The End -