跳到主要内容

基础网络配置

配置静态 IP 和默认路由

软路由需要配置一个静态 IP 和一个默认路由,Ubuntu 可以使用 netplan 来配置,配置文件路径是 /etc/netplan/config.yaml,通过 netplan apply 执行生效。下面根据不同方案给出一些配置示例。

主路由方案配置

对于主路由方案,需要选一个网口用来连接光猫来拨号上网,再选一个网口配置内网静态 IP 并连接交换机,用于内网通信和路由转发,下面是我用过的配置:

/etc/netplan/config.yaml
network:
version: 2
renderer: networkd
ethernets:
enp1s0: # 拨号网口
optional: true
accept-ra: false
dhcp4: no
dhcp6: no
addresses:
- 192.168.11.1/24
routes: # k3s 需要默认路由,不然会报错,导致 dhcp 服务起不来,从而导致局域网连不上,这里随便设置一个(启动会被pppoe拨号覆盖,这里设置用于没有拨号的情况下也连上机器)
- to: default
via: 192.168.11.1
enp2s0:
optional: true
accept-ra: false
dhcp4: no
dhcp6: no
addresses: # 固定网卡所拥有的内网IP地址段
- 10.10.10.2/24
- fddd:dddd:dddd:dddd::2/64
enp6s0: # 预留的管理网口,极端情况下用网线连管理网口登录 ssh
optional: true
accept-ra: false
dhcp4: no
dhcp6: no
addresses:
- 10.10.11.1/24

解释一下:

  • 我的路由器有 6 个网口,Ubuntu 默认使用 enp*s0 的命名方式自动给网口分配网卡名称。
  • 第一个网口我用来拨号上网,上联是光猫(光猫设置桥接,不要光猫的路由功能)。设置用第一个网口来做 PPPoE 拨号的话,会自动修改默认路由走虚拟出来的 ppp0 网卡,这里配置的默认路由不重要。
  • 第二个网口设置一个内网静态 IP,用于内网通信。内网网段我计划用 10.10.10.0/24,软路由静态 IP 使用 10.10.10.2,如果要用 IPv6,也得分配个固定的内网 IPv6 地址,写到 addresses 里。
  • 使用静态 IP,禁用掉 dhcp 动态获取 IP 的能力,所以每个网口的 dhcp4dhcp6 均设为 false。

旁路由方案配置

对于旁路由方案,不需要拨号,主要选一个网口来配置内网静态 IP 就行,这个网口连上交换机,配置示例:

/etc/netplan/config.yaml
network:
version: 2
renderer: networkd
ethernets:
enp1s0: # 主网口,默认路由指向主路由 IP
optional: true
accept-ra: false
dhcp4: no
dhcp6: no
addresses:
- 10.10.10.2/24
- fddd:dddd:dddd:dddd::2/64
routes:
- to: default
via: 10.10.10.14
enp6s0: # 预留的管理网口,极端情况下用网线连管理网口登录 ssh
optional: true
accept-ra: false
dhcp4: no
dhcp6: no
addresses:
- 10.10.11.1/24

桥接

如果需要,其它剩余网口设置桥接,当做交换机用,方面接入更多设备。可以在 netplan 配置里加下 bridges 配置:

  bridges:
br0:
dhcp4: no
interfaces:
- enp3s0
- enp4s0
- enp5s0

配置拨号上网

旁路由方案的拨号上网这里不做介绍,不同场景配置方法各不相同,比如主路由是华为、小米路由器设备,需登录路由器管理页面进行配置;如果是让光猫来拨号,需登录光猫进行配置;如果使用双软路由方案,比如在 EXSI 里虚拟出 RouterOS 作为主路由,那么就登陆 RouterOS 主路由页面进行配置拨号上网。

这里只给出主路由方案的 Ubuntu 系统配置 PPPoE 拨号的方法。

首先是先有鸡还是先有蛋问题,在配置 PPPoE 拨号之前,我们需安装 pppoeconf 并使用它配置 PPPoE,但没有拨号的情况下又无法联网,安装不了。这时,确保你的 Ubuntu 还不是主路由,可以先用普通路由器配置拨号上网,在 netplan 配置中主网口处设置默认路由,即 routes 下的 via 填当前实际拨号上网的路由器 IP 地址,然后执行 netplan apply 让配置生效,测试没问题后再安装 pppoeconf 并用它配置 PPPoE:

# 安装 pppoeconf
sudo apt install -y pppoeconf
# 配置
sudo pppoeconf

根据提示配置好 PPPoE 拨号后,还需要实现 Ubuntu 开机自动执行 PPPoE 拨号,可以用 networkd-dispatcher 来实现:

/etc/networkd-dispatcher/carrier.d/setup-pppoe.sh
#!/bin/env sh

# interface to pppoe workload
INTERFACE=enp1s0

if [ "${IFACE}" = "${INTERFACE}" ] ; then
echo "running pon ${INTERFACE}..."
pon dsl-provider
fi

如果不生效,可以在 rc.local 开机脚本里做(目前本人就是这么做的):

/etc/rc.local
#!/bin/bash

echo "run pppoe"
pon dsl-provider

确保 rc-local 服务处于 enabled 状态: systemctl enable rc-local

另外,路由器上网需要配置 IP MASQUERADE,即确保让出公网的报文的源 IP 自动 SNAT 成本机公网 IP,这样才能正常收到回包,我是通过 nftables 配置的,以下是 nftables 配置文件:

#!/sbin/nft -f

table inet ppp
delete table inet ppp

table inet ppp {
chain postrouting {
type nat hook postrouting priority 100; policy accept;
oifname != "ppp0" return
meta l4proto { tcp, udp } ip saddr 10.10.0.0/16 counter masquerade
meta l4proto { tcp, udp } ip6 saddr fddd:dddd:dddd:dddd::/64 counter masquerade
}
}

配置混杂模式

对于软路由,配置网卡为混杂模式很重要,因为作为路由器,需要监听所有流量,这样才能做路由转发。可以在 /etc/network/if-up.d/ 目录下配置脚本,实现开机自动为所有网卡打开混杂模式:

/etc/network/if-up.d/set-promisc
#!/bin/bash

for i in {1..6}
do
/sbin/ip link set enp${i}s0 promisc on
done

/sbin/ip link set br_lan promisc on

配置防火墙

对于主路由方案,在 Ubuntu 里配置防火墙,可以用 nftables 来声明式配置:

#!/sbin/nft -f

table inet firewall
delete table inet firewall

table inet firewall {
chain prerouting {
type filter hook prerouting priority mangle; policy drop;

iifname != ppp0 accept comment "only care about ppp0"

ip saddr 192.168.43.0/24 counter accept

udp dport > 32767 counter accept

# Permit established and related connections
ct state established,related \
accept \
comment "Permit established/related connections"

# Permit inbound IKEv2 traffic
udp dport { 500, 4500 } \
counter \
accept \
comment "Permit inbound IKEv2 traffic"

# Permit inbound k3s traffic
tcp dport { 6443 } \
counter \
accept \
comment "Permit inbound k3s traffic"

# Permit inbound traceroute UDP ports but limit to 500 PPS
udp dport 33434-33524 \
limit rate 500/second \
counter \
accept \
comment "Permit inbound UDP traceroute limited to 500 PPS"

# Permit inbound SSH
tcp dport { 22, 2456, 24567 } \
counter \
accept \
comment "Permit inbound SSH connections"

# Permit aria2 listen port
meta l4proto { tcp, udp } \
th dport 16881 \
counter \
accept \
comment "Permit aria2 listen port"

# Log and drop new TCP non-SYN packets
tcp flags != syn ct state new \
limit rate 100/minute burst 150 packets \
log prefix "IN - New !SYN: " \
comment "Rate limit logging for new connections that do not have the SYN TCP flag set"
tcp flags != syn ct state new \
counter \
drop \
comment "Drop new connections that do not have the SYN TCP flag set"

# Log and drop TCP packets with invalid fin/syn flag set
tcp flags & (fin|syn) == (fin|syn) \
limit rate 100/minute burst 150 packets \
log prefix "IN - TCP FIN|SIN: " \
comment "Rate limit logging for TCP packets with invalid fin/syn flag set"
tcp flags & (fin|syn) == (fin|syn) \
counter \
drop \
comment "Drop TCP packets with invalid fin/syn flag set"

# Log and drop TCP packets with invalid syn/rst flag set
tcp flags & (syn|rst) == (syn|rst) \
limit rate 100/minute burst 150 packets \
log prefix "IN - TCP SYN|RST: " \
comment "Rate limit logging for TCP packets with invalid syn/rst flag set"
tcp flags & (syn|rst) == (syn|rst) \
counter \
drop \
comment "Drop TCP packets with invalid syn/rst flag set"

# Log and drop invalid TCP flags
tcp flags & (fin|syn|rst|psh|ack|urg) < (fin) \
limit rate 100/minute burst 150 packets \
log prefix "IN - FIN:" \
comment "Rate limit logging for invalid TCP flags (fin|syn|rst|psh|ack|urg) < (fin)"
tcp flags & (fin|syn|rst|psh|ack|urg) < (fin) \
counter \
drop \
comment "Drop TCP packets with flags (fin|syn|rst|psh|ack|urg) < (fin)"

# Log and drop invalid TCP flags
tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|psh|urg) \
limit rate 100/minute burst 150 packets \
log prefix "IN - FIN|PSH|URG:" \
comment "Rate limit logging for invalid TCP flags (fin|syn|rst|psh|ack|urg) == (fin|psh|urg)"
tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|psh|urg) \
counter \
drop \
comment "Drop TCP packets with flags (fin|syn|rst|psh|ack|urg) == (fin|psh|urg)"

# Drop traffic with invalid connection state
ct state invalid \
limit rate 100/minute burst 150 packets \
log flags all prefix "IN - Invalid: " \
comment "Rate limit logging for traffic with invalid connection state"
ct state invalid \
counter \
drop \
comment "Drop traffic with invalid connection state"

# Permit IPv4 ping/ping responses but rate limit to 2000 PPS
ip protocol icmp icmp type { echo-reply, echo-request } \
limit rate 2000/second \
counter \
accept \
comment "Permit inbound IPv4 echo (ping) limited to 2000 PPS"

# Permit all other inbound IPv4 ICMP
ip protocol icmp \
counter \
accept \
comment "Permit all other IPv4 ICMP"

# Permit IPv6 ping/ping responses but rate limit to 2000 PPS
icmpv6 type { echo-reply, echo-request } \
limit rate 2000/second \
counter \
accept \
comment "Permit inbound IPv6 echo (ping) limited to 2000 PPS"

## Permit all other inbound IPv6 ICMP
meta l4proto { icmpv6 } \
counter \
accept \
comment "Permit all other IPv6 ICMP"

# Log any unmatched traffic but rate limit logging to a maximum of 60 messages/minute
# The default policy will be applied to unmatched traffic
limit rate 60/minute burst 100 packets \
log prefix "IN - Drop: " \
comment "Log any unmatched traffic"

# Count the unmatched traffic
counter \
comment "Count any unmatched traffic"
}
}

确保 nftables 服务处于 enabled 状态: systemctl enable nftables

配置内核参数

/etc/sysctl.d/10-router.conf

# 作为路由器,启用 ip 转发 (ipv6默认关闭)
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
net.ipv6.conf.default.forwarding=1

# 接收来自运营商(ISP) 的 ipv6 RA (路由通告),以获取公网 ipv6 地址
#net.ipv6.conf.all.accept_ra=2
#net.ipv6.conf.enp1s0.accept_ra=2
#net.ipv6.conf.default.accept_ra=2
#net.ipv6.conf.all.accept_ra_rt_info_max_plen=128
#net.ipv6.conf.default.accept_ra_rt_info_max_plen=128
#net.ipv6.conf.enp1s0.accept_ra_rt_info_max_plen=128

# 禁用ipv6
net.ipv6.conf.all.accept_ra=0
net.ipv6.conf.enp1s0.accept_ra=0
net.ipv6.conf.default.accept_ra=0
net.ipv6.conf.all.accept_ra_rt_info_max_plen=0
net.ipv6.conf.default.accept_ra_rt_info_max_plen=0
net.ipv6.conf.enp1s0.accept_ra_rt_info_max_plen=0

# 可选。暂时没发现什么场景一定要禁用 rp_filter,以防万一,先禁用
net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.default.rp_filter=0

# 允许容器ns的流量被拦截
net.bridge.bridge-nf-call-iptables=0
net.bridge.bridge-nf-call-ip6tables=0

删除自带的一些内核参数配置,避免冲突:rm /etc/sysctl.d/10-network-security.conf