Featured image of post 使用 dae 配置高性能透明代理软路由[Linux/Ubuntu]

使用 dae 配置高性能透明代理软路由[Linux/Ubuntu]

基本信息

环境:Ubuntu24.04,已安装docker(本文全栈基于 Docker compose 配置,便于管理),可以正常访问hub.docker.com(,可以先用普通代理拉取镜像),所有操作在root权限下运行。

网络拓扑:上级网络(光猫)->主机@enp1s0做wan口->主机@enp2s0做lan口->有线中继 WiFi 等局域网设备。

完整的docker compose配置文件见文末。

软路由基本配置

配置网卡启用桥接网络

1
$ apt install bridge-utils

使用netplan工具配置网卡,将 enp1s0作为wan口连接上级网络,enp2s0作为lan口连接局域网设备,在 enp2s0上建立桥接网络以将局域网与上级网络连接:

1
$ vim /etc/netplan/00-installer-config.yaml

依据网络环境修改并添加以下内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
network:
  ethernets:
    enp1s0:
      # 配置静态ip上网,也可设置为true以使用上级网络dhcp配置网络,使用dhcp时下列配置均不需要
      dhcp4: no
      addresses:
        - 192.168.1.100/24
      routes:
        - to: default
          via: 192.168.1.1
          metric: 100
          on-link: true
      nameservers:
        addresses:
          - 223.5.5.5
          # 后续在桥接网络上配置dns服务,也可先设置为公共dns以确保网络始终可用
    enp2s0:
      dhcp4: no

  # 建立桥接网络将局域网设备接入上层网络,其中99可更改为任意网段
  bridges:
    br0:
      dhcp4: no
      addresses:
        - 192.168.99.2/24
      nameservers:
        addresses:
          - 223.5.5.5
          # 后续在桥接网络上配置dns服务,也可先设置为公共dns以确保网络始终可用
      interfaces:
        - enp2s0
  version: 2
  renderer: NetworkManager

应用配置并查看信息:

1
2
3
$ netplan apply

$ brctl show

桥接网络配置应包含类似以下信息:

1
2
bridge name	   bridge id		    STP enabled	   interfaces
br0		       8000.6aa01d4c1f71	no		       enp2s0

配置dns与dhcp服务器

本文使用adguardhome提供dns服务,dnsmasq、smartdns、mosdns等均可。

调整 systemd-resolved 服务

由于dae会劫持dns并自行分流,需要占用53/udp端口,因此首先调整Ubuntu自带dns Resolve服务器:

1
2
3
4
# vim /etc/systemd/resolved.conf

DNS=8.8.4.4  # 不要填br0接口地址,会导致dae关闭时无法访问网络
DNSStubListener=no  # 关闭dns服务以取消端口占用

随后重启 systemd-resolved 服务以取消dns端口占用:

1
2
3
$ systemctl restart systemd-resolved
$ systemctl disable systemd-resolved --now
  # 可选,防止systemd-resolved影响后续配置

使用 lsof指令检查53端口占用情况:

1
2
$ apt install lsof
$ lsof -i :53

lsof输出应没有任何内容,若存在 systemd-resolved服务则需要重新调整。

使用 docker 配置 AdGuardHome

使用docker compose进行配置,配置文件如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
services:
  adguard:
    image: adguard/adguardhome:latest
    container_name: adguard
    restart: unless-stopped
    # 使用host网络模式以便直接监听主机端口
    network_mode: host
    volumes:
      # 这里第一个目录位置可以自己在主机上选择
      - /opt/adguardhome/conf:/opt/adguardhome/conf
      - /opt/adguardhome/work:/opt/adguardhome/work

在 AdGuardHome 中启用 dhcp 服务器

直接通过 AdGuardHome 直接启用 dhcp 服务器,需要注意关闭现有的 dhcp 服务,可通过 htop 等手段检查 dhcpd 服务运行情况

1
2
3
4
systemctl stop isc-dhcp-server
systemctl disable isc-dhcp-server
# 检查 dhcp服务 67 端口是否被占用
lsof -i :67

修改/opt/adguardhome/conf/AdGuardHome.yaml,设置监听地址和端口:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
http:
  pprof:
    port: 6060
    enabled: false
  address: 192.168.1.100:5253 # 网页管理端口
  session_ttl: 720h
dns:
  bind_hosts:
    - 192.168.1.100 # enp1s0口地址,可选
    - 192.168.99.2 # br0口地址
  port: 53
  # 可以直接设置为53,使用dae内置的dns 处理将之转发给adguardhome
  # 有助于利用adguardhome的安全管理机制

# 自己在对应位置修改
dhcp:
  enabled: true  # 直接在这里强制启用,避免在网页端配置时报接口没有固定 IP 的错误
  interface_name: br0
  local_domain_name: lan
  dhcpv4:
    gateway_ip: 192.168.99.2
    subnet_mask: 255.255.255.0
    range_start: 192.168.99.10
    range_end: 192.168.99.240
    lease_duration: 86400
    icmp_timeout_msec: 1000
    options:
      - 6 ips 192.168.99.2,1.0.0.1  # 增加 1.0.0.1 作为备用 dns 以防止adguardhome不可用
  dhcpv6:
    range_start: ""
    lease_duration: 86400
    ra_slaac_only: false
    ra_allow_slaac: false

配置完成后,启动 AdGuardHome 容器:

1
docker compose up -d adguard

访问192.168.1.100:5253,进入网页配置,配置dns上游服务器,选择合适的广告屏蔽器,以下提供一些上游服务器例子,自行测试速度并选择使用:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 阿里云
https://223.5.5.5/dns-query
tls://223.5.5.5
https://223.6.6.6/dns-query
tls://223.6.6.6

# 腾讯云
https://doh.pub/dns-query
tls://dot.pub
tls://120.53.53.53
# tls://1.12.12.12 # 这俩选快的用
# 119.29.29.29

# 国际
# https://dns.google/dns-query
tls://dns.google
# https://cloudflare-dns.com/dns-query
https://1.1.1.1/dns-query
tls://1.1.1.1

配置完成后,使用 lsof检查,应有快速输出(若输出缓慢可能存在dns配置问题),类似以下信息:

1
2
3
4
5
6
7
$ lsof -i :53  # 上文设置的端口

COMMAND       PID USER   FD   TYPE    DEVICE SIZE/OFF NODE NAME
AdGuardHo 2645397 root   15u  IPv4 119818232      0t0  UDP 192.168.1.100:domain 
AdGuardHo 2645397 root   16u  IPv4 119818233      0t0  UDP 192.168.99.2:domain 
AdGuardHo 2645397 root   17u  IPv4 119818234      0t0  TCP 192.168.1.100:domain (LISTEN)
AdGuardHo 2645397 root   18u  IPv4 119818236      0t0  TCP 192.168.99.2:domain (LISTEN)

dhcp Snooping 配置(可选)

为避免局域网内部有人插错路由器 LAN 口导致 dhcp 服务器冲突(现代路由器基本不会出现这一情况),可以在软路由当中限制仅接受来自 br0 接口的 dhcp 请求,下面的代码务必正确替换br0接口的网关 MAC 地址.

该操作存在风险,如果无法正常申请到 IP 地址可以使用ebtables -F清除规则来回滚:

1
2
3
4
5
6
7
8
9
apt install ebtables -y
# 注意下面的 mac 地址替换为真正的网关 mac 地址
ebtables -A INPUT -p IPv4 --ip-proto udp --ip-sport 68 --ip-dport 67 -j ACCEPT
ebtables -A INPUT -p IPv4 --ip-proto udp --ip-sport 67 --ip-dport 68 -s ! 11:22:33:44:55:66 -j DROP
# 查看规则是否生效
ebtables -L

# 如果执行上述操作后,新设备无法正确获取 IP 地址,可以使用下面的命令清除规则来回滚
ebtables -F

转发与路由配置

配置主机转发能力:

1
2
3
4
5
# vim /etc/sysctl.conf

net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
net.ipv4.tcp_congestion_control=bbr

应用配置:

1
$ sysctl -p /etc/sysctl.conf

使用 iptables启用路由能力:

1
2
3
$ iptables -A FORWARD -s 192.168.0.0/16 -j ACCEPT  # 局域网,可依据自身环境修改为10.0.0.0/24等
$ iptables -A FORWARD -s 172.16.0.0/12 -j ACCEPT   # docker网络
$ iptables -t nat -A POSTROUTING -j MASQUERADE     # 应用nat伪装源ip地址

若使用 ufw,应用以下规则:

1
2
3
$ ufw allow from 172.16.0.0/12   # docker的桥接网络地址
$ ufw allow from 192.168.0.0/16  # 局域网
$ ufw reload 

至此,软路由基本配置完成,主机可作为一个普通的高性能路由器使用。

基于 dae 配置透明代理访问 ChatGPT

使用docker compose配置,配置文件如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
services:
  dae:
    image: daeuniverse/dae:latest
    container_name: dae
    network_mode: host
    privileged: true
    pid: host
    restart: unless-stopped
    volumes:
      - /sys:/sys
      - /etc/dae:/etc/dae
    depends_on:
      - adguard

对于dae的配置文件/etc/dae/config.dae,可以参考官网配置,下面给出我的关键配置,在对应位置修改或增加即可:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
global {
    lan_interface: enp1s0, enp2s0, br0, docker0
    wan_interface: enp1s0
}

dns {
    ipversion_prefer: 4
    upstream {
        adguard: 'udp://192.168.1.100:53'
    }
    routing {
        request {
            fallback: adguard
            # 截获所有没有指向 adguard 的 dns 请求
            # 这样可以确保 adguardhome dns 过滤可以正常生效
        }
    }
}

node {
    naive-hk: 'socks5://127.0.0.1:1090'
    naive-us: 'socks5://127.0.0.1:1091'
    hy2-us: 'hysteria2://xxxxxxx@1.2.3.4:9443/?sni=x.x.x'
}

group {
  us {
      filter: name(hy2-us)
      filter: name(naive-us)
      policy: min_moving_avg
  }
  hk {
      filter: name(naive-hk)
      policy: min_moving_avg
  }
}

routing {
    # All the rules are matched from top to bottom sequentially.

    ### Preset rules.
    ipversion(6) -> block

    # 服务器 IP (如果用的自己部署的服务器,应绕过代理)
    dip(1.2.3.4, 5.6.7.8) -> direct 

    # 避免无法连接到DoT/DoH服务器
    domain(one.one.one.one, dns.google, dns.google.com, cloudflare-dns.com) -> hk
    dip(1.0.0.1, 1.1.1.1, 8.8.8.8, 8.8.4.4) -> hk

    # 避免代理软件无法连接到更新服务器
    pname(NetworkManager, naive, AdGuardHome, hysteria) -> must_direct

    # 直接将所有指向 adguard 的 dns 流量交还给 adguard 处理,仅拦截对 8.8.8.8 等外部 dns 的处理
    # 这样可以确保 adguardhome 针对 ip 的安全管理可以正常生效
    l4proto(udp) && dip(192.168.99.2, 192.168.1.100) && dport(53) -> must_direct

    # 擅于利用 https://github.com/v2fly/domain-list-community
    # 可以 clone 下来查找自己关心的网站,然后配置其所属类别的网络出口
    # 最好使用精确的类别,类似 geosite:cn 这样的大帽子容易出现误报与重复,他们只适用于兜底

    # 学术网站
    domain(www.easyscholar.cc, ieee.hum.works, seamlessaccess.org, dblp.org) -> direct
    domain(geosite:google-scholar, geosite:sci-hub) -> us
    domain(geosite:category-scholar-cn, geosite:category-scholar-!cn, geosite:apple, geosite:category-ai-cn) -> direct
    # domain(computer.org, acm.org, ieee.org, springer.com, clarivate.com, proquest.com, engineeringvillage.com, wiley.com, elsevier.com, webofknowledge.com, clarivate.cn, sciencedirect.com, sciencedirectassets.com, dblp.org, cnki.net)->direct
    
    domain(geosite:apple) -> direct

    dip(172.16.0.0/12, 224.0.0.0/3, 'ff00::/8', geoip:private) -> direct

    # AI 网站
    domain(geosite:category-ai-!cn, geosite:bing) -> us

    # 日用外国网站
    domain(geosite:google, geosite:amazon, geosite:telegram, geosite:category-entertainment, geosite:category-dev, geosite:protonmail) -> hk
    
    # xxx
    domain(geosite:category-porn) -> hk

    domain(geosite:cn) -> direct
    dip(geoip:cn) -> direct

    fallback: hk
}

完整的 docker-compose.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
services:
  adguard:
    image: adguard/adguardhome:latest
    container_name: adguard
    restart: unless-stopped
    network_mode: host
    volumes:
      - /opt/adguardhome/conf:/opt/adguardhome/conf
      - /opt/adguardhome/work:/opt/adguardhome/work

  dae:
    image: daeuniverse/dae:latest
    container_name: dae
    network_mode: host
    privileged: true
    pid: host
    restart: unless-stopped
    volumes:
      - /sys:/sys
      - /etc/dae:/etc/dae
    depends_on:
      - adguard

  naive_hk:  # 自行配置修改代理容器
    image: docker.io/zydou/naiveproxy:latest
    container_name: naive_hk
    ports:
      - 127.0.0.1:1090:1090
    restart: unless-stopped
    command: naive --listen=socks://0.0.0.0:1090 --proxy=quic://xxx:xxx@xxx.example.com

参考

使用 Hugo 构建
主题 StackJimmy 设计