Linux软路由配置

Haixin Pang 二月 25, 2025 更新: 十月 14, 2025 #Network #Router

systemd-networkd + systemd-resolved

本节参考Arch Manual

假设我们有两个网口enp1s0enp2s0enp1s0作为WAN口,enp2s0作为LAN口。

多个LAN口可以通过桥接的方式来实现,具体配置方式根据网络管理器自行查阅。

基本网络配置

将以下配置写入/etc/systemd/network/10-enp1s0.network文件

[Match]
MACAddress=xx:xx:xx:xx:xx:xx

[Network]
DHCP=ipv4
IPForward=yes
# ipv6配置
IPv6AcceptRA=yes

[DHCP]
RouteMetric=100
UseMTU=true

以上配置中MACAddress填写enp1s0MAC地址。 配置enp1s0通过DHCP获取ipv4地址,并且开启ip转发功能。 ipv6配置中开启IPv6AcceptRA,表示接受路由器通告。

将以下配置写入/etc/systemd/network/20-enp2s0.network文件

[Match]
MACAddress=xx:xx:xx:xx:xx:xx

[Network]
DHCPServer=yes
IPMasquerade=both
Address=192.168.5.1/24
# ipv6配置
Address=fd00:1::/64
IPv6SendRA=yes

[DHCPServer]
PoolOffset=3
DNS=_server_address

# 静态分配
[DHCPServerStaticLease]
MACAddress=xx:xx:xx:xx:xx:xx
Address=192.168.5.2

# ipv6配置
[IPv6SendRA]
DNS=_link_local

[IPv6Prefix]
Prefix=fd00:1::/64

[IPv6RoutePrefix]
Route=fd00:1::/64

以上配置中MACAddress填写enp2s0MAC地址。 配置enp2s0开启DHCP服务,并且开启ip伪装功能。 Address配置enp2s0ipv4地址为192.168.5.1/24DHCPServer配置中DNS=_server_address表示将LAN口的地址作为DNS服务器地址,需配合DNS服务使用。 ipv6配置中配置ipv6地址为fd00:1::/64,并且开启IPv6SendRA,表示发送路由器通告。

注意:如果以上配置不生效,检查net.ipv4.ip_forwardnet.ipv6.conf.all.forwarding是否开启。具体配置方式自行查阅。

Note - FAQ - systemd-networkd

DNS配置

将以下配置写入(修改至)/etc/systemd/resolved.conf文件

...
[Resolve]
...
DNSStubListener=yes
DNSStubListenerExtra=192.168.5.1
...

开启DNSStubListenerExtra,并指定LAN口的地址。

更多DNS配置请参考Note - DNS

启动服务

sudo systemctl enable --now systemd-networkd systemd-resolved

其它搭配软件

netplan

本节参考Netplan.io

注意netplan目前还不支持DHCPServerIPMasquerade配置。 可以通过netplan来配置网口

# /etc/netplan/01-netcfg.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    enp1s0:
      dhcp4: true
      accept-ra: true
    enp2s0:
      addresses: 
        - 192.168.5.1/24
        - fd00:1::1/64

如果选择systemd-networkd作为渲染器,则不要在/etc/systemd/network/目录下配置网口,否则将会覆盖netplan的配置。

应用配置

sudo netplan apply

dnsmasq

本节参考Arch Wiki - Dnsmasq

dnsmasq可以作为DNSDHCP服务来使用。 将以下配置写入/etc/dnsmasq.d/lan.conf文件

interface=enp2s0

# 只启用 DHCP
port=0

listen-address=fd00:1::1,192.168.5.1

# DHCP 地址池
dhcp-range=192.168.5.3,192.168.5.255,24h

# 网关(可选)
dhcp-option=3,192.168.5.1

# DNS 服务器
dhcp-option=6,192.168.5.1

dhcp-host=98:fc:84:e5:13:6a,192.168.5.2

enable-ra

dhcp-range=fd00:1::100,fd00:1::ffff,64,12h

注意这里dnsmasq没有配置自带的DNS服务。

应用同时配置自动启动

sudo systemctl enable --now dnsmasq

Masquerade配置

如果不使用systemd-networkdIPMasquerade功能,同样需要配置NAT转发功能。

同时注意net.ipv4.ip_forwardnet.ipv6.conf.all.forwarding需要开启。

这里可以选择用iptables或者nftables来配置Masquerade。 注意如果机器上同时配有其他使用iptables的服务如DockerTailScale,则建议使用iptables,或者安装nftables但是用iptables的兼容模式。

iptables

sudo iptables -t nat -A POSTROUTING -o enp1s0 -j MASQUERADE
sudo iptables -A FORWARD -i enp2s0 -o enp1s0 -j ACCEPT
sudo iptables -A FORWARD -i enp1s0 -o enp2s0 -m state --state RELATED,ESTABLISHED -j ACCEPT
# ipv6
sudo ip6tables -t nat -A POSTROUTING -o enp1s0 -j MASQUERADE
sudo ip6tables -A FORWARD -i enp2s0 -o enp1s0 -j ACCEPT
sudo ip6tables -A FORWARD -i enp1s0 -o enp2s0 -m state --state RELATED,ESTABLISHED -j ACCEPT

可以使用iptables-persistent来保存iptables规则

sudo apt install iptables-persistent

应该在安装过程中选择保存当前规则。没有则查看是否有/etc/iptables/rules.v4/etc/iptables/rules.v6文件,如果没有则手动保存

sudo iptables-save > /etc/iptables/rules.v4
sudo ip6tables-save > /etc/iptables/rules.v6

nftables

#!/usr/sbin/nft -f
#/etc/nftables.conf
table ip nat {
    chain postrouting {
        type nat hook postrouting priority 100;
        counter oif "enp1s0" masquerade
    }
}
table ip filter {
    chain forward {
        type filter hook forward priority 0; policy drop;
        iif "enp2s0" oif "enp1s0" accept
        iif "enp1s0" oif "enp2s0" ct state related,established accept
    }
}
table ip6 nat {
    chain postrouting {
        type nat hook postrouting priority 100;
        counter oif "enp1s0" masquerade
    }
}
table ip6 filter {
    chain forward {
        type filter hook forward priority 0; policy drop;
        iif "enp2s0" oif "enp1s0" accept
        iif "enp1s0" oif "enp2s0" ct state related,established accept
    }
}

应用同时配置自动启动

sudo systemctl enable --now nftables