amtoaer

晓风残月

叹息似的渺茫,你仍要保存着那真!
github
x
telegram
steam
nintendo switch
email

[NAS 系列第三弹]为局域网设备配置无感知的透明代理

记得我上篇文章中有提到:

本篇不解决网络问题,默认 docker 镜像等均可连接外网,如果不行请手动为镜像配置 HTTP_PROXY、HTTPS_PROXY。

今天这篇文章就来分享一下我的网络配置。经过配置后,可以让任何一台通过有线或无线方式连接到局域网中的设备,无需任何配置就可连接外网,并可以使用非常简单的语法做到 DNS 和流量分流。

整体思路是将 NAS 作为旁路网关,让 dhcp 返回的默认网关指向 NAS,在 NAS 侧配置代理工具。老样子,在开始之前写几条声明:

  1. 本文中提到的代理工具 dae 需要内核版本 >= 5.8,如不符合需要换用其它代理工具;
  2. 本人 NAS 网络使用 Network Manager 配置,其它工具请自行查找替代写法;
  3. 不同家庭的网络配置和结构不同,或许不能原样照搬,但基本原理相同;
  4. ALL IN ONE, ALL IN BOOM !

网络结构#

家里的网络结构如下图所示(原谅我拙劣的作图手法):

image

可以看到我并没有单独的路由器,拨号、NAT、无线 AP 都由内置路由的光猫代劳,只需要把所有设备连接到光猫即可上网。

因为所有设备都在同个网段,实现代理非常简单,整体来说分为三个步骤:

  1. 把 NAS 的所有网口桥接(可跳过,主要是拓展有线接口)
  2. 固定光猫和 NAS 的 IP 地址
  3. 在 NAS 上配置代理和 IP 转发
  4. 修改 DHCP 服务器,将默认网关指向 NAS

下面展开说明。

桥接 NAS 的所有网口(可跳过)#

我 NAS 的主板上自带一个网口,因为担心光猫网口不够用,所以单独购入了一块四口 pcie 网卡做桥接:

IMG_20230804_205220

插上之后执行 ifconfig,发现我的五个网口编号依次是 enp3s0、enp4s0、enp5s0、enp6s0、enp7s0。使用 Network Manager 可以很方便地桥接网口:

# 新建一个网桥
sudo nmcli connection add type bridge ifname br0 stp no
# 把物理网口全加到网桥里
sudo nmcli connection add type bridge-slave ifname enp3s0 master br0
sudo nmcli connection add type bridge-slave ifname enp4s0 master br0
sudo nmcli connection add type bridge-slave ifname enp5s0 master br0
sudo nmcli connection add type bridge-slave ifname enp6s0 master br0
sudo nmcli connection add type bridge-slave ifname enp7s0 master br0

固定光猫和 NAS 的 IP 地址#

光猫略过不表,因为其在一般情况下 IP 都是固定的(如 192.168.0.1、192.168.1.1),此处需要固定 NAS 的 IP 地址。

使用 sudo nmcli connection show 可以看到所有的连接,位于前面并且高亮的是活跃的连接:

image

如上图所示,一般使用最前面的连接就可以。

注:如果刚刚桥接了网口,那么桥接的 bridge-xx 默认不会启用,这种情况下应该使用 bridge-xx 而非最前面的连接。

以 bridge-br0 为例,固定 IP 地址的命令如下:

# 固定你的 ip 和网关(需要和光猫在同个网段)
sudo nmcli connection modify bridge-br0 ipv4.addresses 192.168.1.250/24 ipv4.gateway 192.168.1.1
# 使用你想要的 dns
sudo nmcli connection modify bridge-br0 ipv4.dns 119.29.29.29
# 调整 ipv4 地址分配方式为手动
sudo nmcli connection modify bridge-br0 ipv4.method manual
# reload 一下
sudo nmcli connection reload

注:同样对于刚刚桥接过的情况,这里还需要启用桥接的所有网口,停用现有 connection 并启用 bridge:

# 启用桥接的所有网口
sudo nmcli connection up bridge-slave-enp3s0
sudo nmcli connection up bridge-slave-enp4s0
sudo nmcli connection up bridge-slave-enp5s0
sudo nmcli connection up bridge-slave-enp6s0
sudo nmcli connection up bridge-slave-enp7s0
# 停用正在使用的 connection
sudo nmcli connection down Wired\ connection\ 6
# 启用刚刚配置好的 bridge
sudo nmcli connection up bridge-br0

在 NAS 上配置代理和 IP 转发#

来到了最关键的一步,配置代理和 IP 转发。

IP 转发#

首先启用 IP 转发,这将允许这台设备作为网关转发其它设备的流量:

sudo vim /etc/sysctl.d/30-ipforward.conf

# 写入如下内容并保存
net.ipv4.ip_forward=1
net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1

# 重载
sudo sysctl --system

代理#

本篇使用的代理工具是 dae,实践中为了操作方便,往往使用带有 webui 的 daed:

daed, a modern dashboard for dae.

在 Arch Linux 上安装非常简单,使用如下命令安装并自启动:

sudo pacman -S daed
sudo systemctl enable --now daed.service

打开 NAS 的 2023 端口,输入初始化的账号密码,就能看到主页面了:

image

整体的操作逻辑非常简单,在右下方添加订阅,并把订阅或节点拖动到左下方的群组中即可。在 DNS 和路由模块中点击编辑按钮即可展开配置,编写分流规则。

dae 的分流规则继承了 v2raya,语法简单明了,下面是我的 DNS 和路由规则样例:

# dns 规则

upstream {
  googledns: 'tcp+udp://dns.google.com:53'
  alidns: 'udp://dns.alidns.com:53'
}
routing {
  request {
    # 阻断广告的 dns 解析
    qname(geosite:category-ads) -> reject
    qname(geosite:category-ads-all) -> reject
    # 默认使用 alidns 查询
    fallback: alidns
  }
  response {
    # 上游是 googledns 直接通过,避免回环
    upstream(googledns) -> accept
    # 非国内网站解析到了局域网 ip,认为是遇到 dns 污染,重新在 googledns 查一次
    !qname(geosite:cn) && ip(geoip:private) -> googledns
    # 其它情况直接 accept
    fallback: accept
  }
}
# 路由规则

# 在默认规则的基础上添加了 qbittorrent 的直连
pname(NetworkManager, systemd-resolved, qbittorrent-nox) -> direct
# 阻断广告连接
domain(geosite:category-ads, geosite:category-ads-all) -> block
# 一般梯子都不支持 ipv6,走直连
ipversion(6) -> direct
# 对于 chatgpt,走固定的节点组
domain(geosite:openai, regex: ".+\.openai$") -> chatgpt
# 广播地址、局域网地址和国内 ip,走直连
dip(224.0.0.0/3, 'ff00::/8', geoip:private, geoip:cn) -> direct
# steam、国内域名走直连
domain(geosite:steam@cn, geosite:cn, geosite:geolocation-cn) -> direct
# 未匹配,走代理
fallback: proxy

分流规则设置完毕后,需要在配置中设置需要绑定的接口。在旁路网关的使用场景中,LAN 和 WAN 中都应该添加当前活跃的接口(对于我来说是 br0),此外 LAN 口还可以添加一些其它需要代理的接口(如 docker0):

image

其它选项一般不需要修改,点击最下面的提交,接着在主页右上角点击启动即可。

image

此时 NAS 和所有网关指向 NAS 的设备产生的流量均会被 dae 接管分流,实现了透明代理。

修改 DHCP 服务器,将默认网关指向 NAS#

虽然现在网关指向 NAS 即可透明代理,但 DHCP 返回的网关仍然是 192.168.1.1(即光猫路由器的地址),接入到网络的设备需要手动修改网关才能成功代理。为了改变这种情况,需要调整 DHCP 服务器。

光猫路由器内提供的 DHCP 服务器没办法修改返回的网关地址,因此需要在 NAS 上启动一个 DHCP 服务器,并用其替代光猫路由器上的 DHCP 服务器。

在 NAS 上部署 DHCP 服务器#

Linux 上可用的 DHCP 服务器有很多,个人选用的是 dhcpd 的继任者 kea,dnsmasq 也能实现同样的目的:

A modern, scalable, robust DHCPv4 and DHCPv6 server, with database (MySQL, PostgreSQL), hooks, multi-threading, RADIUS, NETCONF, Kerberos and more.

在 Arch Linux 中安装:

sudo pacman -S kea

在这里我们只需要替换掉 dhcp4 即可满足需求。参考官方文档编写 dhcp 配置如下:

{ "Dhcp4":

{
  "interfaces-config": {
    "interfaces": [ "br0" ]
  },

  "lease-database": {
      "type": "memfile",
      "lfc-interval": 3600
  },

  "valid-lifetime": 4000,


  "subnet4": [
    {
       "pools": [ { "pool":  "192.168.1.2 - 192.168.1.254" } ],
       "subnet": "192.168.1.0/24",
       "interface": "br0",
       "option-data": [
         {
             "name": "domain-name-servers",
             "data": "119.29.29.29"
         },
         {
             "name": "routers",
             "data": "192.168.1.250"
         },
      ]
    }
  ],
    "loggers": [
        {
            "name": "kea-dhcp4",
            "output_options": [
                {
                    "output": "stdout"
                }
            ],
            "severity": "INFO"
        }
    ]
}

}

将上述配置写入 /etc/kea/kea-dhcp4.conf,并启动 kea-dhcp4 服务:

sudo systemctl enable --now kea-dhcp4.service

接着登录光猫路由器的后台,关闭自带的 dhcp4 服务器:

image

现在随便使用某台有线或无线设备连接到网络中,查看 dhcp 是否正常工作:

image

看到路由器位置显示的地址是我们设置的 192.168.1.250,说明 NAS 上部署的 dhcp 工作正常。

至此配置完毕,大功告成。

参考资料#

  1. dae dns 文档
  2. dae routing 文档
  3. dae 配置示例
  4. Arch Wiki - Network Bridge
  5. Arch Wiki - Internet Sharing
  6. Kea examples
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.