使用 Debian 服务器作为家庭网关

 Aug. 4, 2019, 11:36 p.m.   0 comments    debian linux router gateway network microserver

前一段时间买了台 HPE Microserver Gen10,考虑到这货有两块千兆网卡,总觉得不把它当成路由器/网关来用有点浪费,于是忍不住拆掉了原来的 EdgeRouter X,开始折腾软路由。

基础配置

连接

Microserver Gen10 有两块网卡,在 Debian 中分别对应 enp2s0f0enp2s0f1,这里我将 enp2s0f0 作为LAN口,连接到家里的交换机,用于连接各种有线设备和无线AP;另一个 enp2s0f1 作为WAN口,连接到光猫。

系统

没什么好说的,习惯用 Debian,其他主流 Linux 发行版应该都可以用。不过在装 Debian 的过程中遇到了些 Microserver 特有的坑,回头再写篇文章详解。

PPPoE 拨号

作为网关,PPPoE 拨号是必须的,安装 pppoeconf 包,然后按照提示配置即可:

sudo apt install pppoeconf
sudo pppoeconf

网关 IP

跟大多数家用路由器一样,网关的LAN口需要拥有一个固定的内网IP地址,这里我设置为 192.168.1.1/24(假设LAN网段为192.168.1.0/24),编辑 /etc/network/interfaces,添加LAN口配置:

allow-hotplug enp2s0f0
auto enp2s0f0
iface enp2s0f0 inet static
    address 192.168.1.1/24

重启 networking 服务使之生效:

sudo systemctl restart networking

DHCP 服务和 DNS 服务

网关开启DHCP服务,给局域网内的设备自动分发IP地址,这里我用的是非常流行的 dnsmasq,不仅可以作为DHCP服务器,还能作为DNS服务器。安装 dnsmasq:

sudo apt install dnsmasq

编辑 /etc/dnsmasq.conf,添加如下配置:

interface=enp2s0f0
listen-address=192.168.1.1
dhcp-range=192.168.1.10,192.168.1.150,255.255.255.0,12h
dhcp-option=3,192.168.1.1

重启 dnsmasq 服务使之生效:

sudo systemctl restart dnsmasq

IP 转发和 NAT

光有IP地址还不够,作为网关,必须要能够转发来自局域网的所有数据。编辑 /etc/sysctl.conf,将 net.ipv4.ip_forward这一行的注释去掉:

net.ipv4.ip_forward=1

然后执行 sudo sysctl -f 使其生效。

同时,为了使局域网内的设备能够访问外网,还需要配置NAT规则:

sudo iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j MASQUERADE

进阶配置

至此,所有局域网设备应该能够通过刚刚设置好的网关访问互联网了。但是既然用 Debian 服务器作为软路由,当然要充分利用 Linux 的灵活性,进行更进一步的配置。

防火墙

屏蔽掉除了 PING 和 SSH 服务以外的一切外部来源请求:

sudo iptables -A INPUT -p icmp -m icmp-type 8 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -i ppp0 -j DROP

Wireguard

为了方便从外网访问家里的局域网,我在一台外网的服务器上配置了 Wireguard,只需要将网关与外网的服务器通过 Wireguard 连接,不论我在哪里,只要能连上 Wireguard 网络,就能穿透互联网回到家中。

Wireguard 的安装可以参考官网介绍 https://www.wireguard.com/install/

安装好 Wireguard 之后,创建 Wireguard 的配置文件,假设为 /etc/wireguard/wg0.conf

[Interface]
PrivateKey = [PRIVATE KEY]
ListenPort = 51820
[Peer]
Endpoint = [ENDPOINT]:51820
PublicKey = [PEER'S PUBLIC KEY]
AllowedIPs = 192.168.10.0/24
PersistentKeepalive = 30

这里使用了端口 51820,因此需要在防火墙开启这一端口:

sudo iptables -I INPUT -p udp -m udp -s ENDPOINT --dport 51820 -j ACCEPT

同时,编辑 /etc/network/interfaces 添加 Wireguard 的相关配置:

auto wg0
iface wg0 inet static
    address 192.168.10.x/24
    pre-up ip link add $IFACE type wireguard
    pre-up wg setconf $IFACE /etc/wireguard/$IFACE.conf
    post-down ip link del $IFACE

启动 Wireguard 后,这时候 Wireguard 的虚拟网络为 192.168.10.0/24,而内网网段为 192.168.1.0/24,为了让连接到 Wireguard 网络的所有设备(比如手机)能够顺利访问到所有内网设备,还需要在网关上进行 NAT 的配置:

sudo iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -j SNAT --to-source 192.168.1.1

这样所有来自 Wireguard 网段的请求的源地址都会被翻译成 192.168.1.1 从而得以访问内网其他设备。此外,还需要在外网的服务器上将 192.168.1.0/24 加入 AllowedIPs,这里贴一个外网服务器的 Wireguard 配置:

[Interface]
ListenPort = 51820
PrivateKey = [PRIVATE KEY]
[Peer]
PublicKey = [PEER'S PUBLIC KEY]
AllowedIPs = 192.168.10.x/32, 192.168.1.0/24
PersistentKeepalive = 30

SS-REDIR 和 SS-TUNNEL

由于家里有两个 Google Home 音箱,为了让它们能够顺利连到 Google,需要在网关上进行相应的配置。这里我选择使用 ss-redir 和 ss-tunnel,其中 ss-redir 用于透明代理,ss-tunnel 用于 DNS 代理。

ss-redir 和 ss-tunnel 的安装和配置可以参考官方介绍 https://github.com/shadowsocks/shadowsocks-libev#transparent-proxy

我将 ss-redir 配置在了1081端口,ss-tunnel 配置在了5300端口。假设 Google Home 音箱的 IP 地址是 192.168.1.x ,只需如下配置即可完成对 TCP 流量的转发:

sudo iptables -t nat -A PREROUTING -p tcp -m tcp -s 192.168.1.x -j REDIRECT --to-port 1081

然而光配置好 TCP 流量的转发还不够,Google Home 音箱使用 Google 的 DNS 服务器进行 DNS 解析,因此需要将其重定向到 ss-tunnel 所在的5300端口:

sudo iptables -t nat -A PREROUTING -p udp -m udp -s 192.168.1.x --dport 53 -j REDIRECT --to-port 5300

解决 DNS 污染

既然有了 ss-tunnel 顺便解决一下 DNS 污染问题吧,把所有的 DNS 请求都转发到国外去请求是不现实的,会导致 DNS 解析时间过长不说还会使很多国内网站解析到国外的 IP 从而使访问变慢。考虑到前面我已经装了 dnsmasq,因此,我选择了dnsmasq-china-list 这个项目来解决 DNS 污染问题。

dnsmasq-china-list 的思路很简单,国内域名用国内 DNS 服务器解析,其他域名用国外 DNS 服务器解析,为了实现这一目的,需要将项目目录中的 accelerated-domains.china.confbogus-nxdomain.china.conf 放到 /etc/dnsmasq.d/ 目录中,同时编辑 /etc/dnsmasq.conf,将上游 DNS 服务器指向 ss-tunnel:

no-resolv
server=192.168.1.1#5300
conf-dir=/etc/dnsmasq.d

重启 dnsmasq 使之生效:

sudo systemctl restart dnsmasq

IPv6

由于江苏联通至今没有提供原生的 IPv6 接入,因此现阶段若要体验 IPv6 还只能通过 HE 提供的 IPv6 Tunnel Broker 接入。

Tunnel Broker 网站上申请好 IPv6 Tunnel 之后, 编辑 /etc/network/interfaces,添加 tunnel 配置:

auto tun0
iface tun0 inet6 v4tunnel
    address [Client IPv6 Address]
    netmask 64
    endpoint [Server IPv4 Address]
    local 0.0.0.0
    ttl 255
    gateway [Server IPv6 Address]

别忘了将 Tunnel Broker 的 Endpoint IPv4 地址加入防火墙白名单:

sudo iptables -I INPUT -s [Server IPv4 Address] -j ACCEPT

网关有了 IPv6 地址之后,还得给局域网内的设备分配 IPv6 地址,这里需要用到 radvd:

sudo apt install radvd

编辑 /etc/radvd.conf,将 Tunnel Broker 分配的 /64 地址段填进去:

interface enp2s0f0
{
    AdvSendAdvert on;
    AdvIntervalOpt on;
    MinRtrAdvInterval 60;
    MaxRtrAdvInterval 300;
    AdvLinkMTU 1280;
    AdvOtherConfigFlag on;
    AdvHomeAgentFlag off;
    prefix [Routed IPv6 Prefix /64]
    {
        AdvOnLink on;
        AdvAutonomous on;
        AdvRouterAddr on;
    };
};

重启 radvd,局域网内的设备应该都能获得 IPv6 地址了:

sudo systemctl restart radvd