创建一台 Linux 路由器设备以模拟弱网环境

在某些时候需要模拟一些弱网环境,而 Linux 本身通过可以配置成一个路由,同时结合流量整形命令 tc 可以达到弱网以及流量限制的功能。

对于流量整形,单个网络适配器只能正对出口带宽进行整形,所以需要配置一台路由以便于双向流量整形 (WAN 及 LAN)。同时此路由设备后面可以接入多台主机设备,以便于统一配置弱网环境。

文本以 CentOS 7 为例在 Windows 桌面环境的 VMware 虚拟机环境下配置一个弱网模拟的路由。

对于其它虚拟机软件或平台,可以找到类似的方法配置网络。对于其它 Linux 发行版也可以找到对应的网络配置,此方法大概率兼容更高的 CentOS 版本以及 RHEL

虚拟机配置

需要两台虚拟机,一台作为路由设备,一台作为客户机。客户机也可以用其它操作系统,例如 Win 10,这里不影响实际配置。

路由机的网卡选择桥接模式(或者NAT,取决于需要)。另外添加一个额外的网适配器,选择自定义网络 VMNet19。

客户机的唯一网络适配器选择自定网络 VMNet19。

配置路由主机网络

网卡的启用配置可以在创建虚拟机时设置,也可以再虚拟机安装完毕后设置。

启用 WAN 和 LAN

使用命令 nmtui 进入图形化网络配置

~]# nmtui

打开两个网卡的 自动连接 选项

同时修改 LAN 网卡为手动配置:

  • 修改IP地址为 10.1.1.1/24
  • 打开 时钟不适用此网络用于默认路由
  • 打开 忽略自动获取的DNS参数

现在路由主机有了两个网卡分别作为 WAN (ens33,192.168.200.171) 和 LAN (ens34,10.1.1.1)

 ~]# ip a
ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:db:94:30 brd ff:ff:ff:ff:ff:ff
    inet 192.168.200.171/24 brd 192.168.200.255 scope global noprefixroute dynamic ens33
    valid_lft 43131sec preferred_lft 43131sec
    inet6 fe80::4a9b:5e96:d28d:6b99/64 scope link noprefixroute
    valid_lft forever preferred_lft forever
ens34: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:db:94:3a brd ff:ff:ff:ff:ff:ff
    inet 10.1.1.1/24 brd 10.1.1.255 scope global noprefixroute ens34
    valid_lft forever preferred_lft forever
    inet6 fe80::742d:21e0:a13f:dac7/64 scope link noprefixroute
    valid_lft forever preferred_lft forever

配置防火墙

现在 WAN (ens33) 和 LAN (ens34) 都默认在 public 网络区中。

在此网络区中启用 masquerade 功能,同时打开 8000 和 5022 端口转发到 10.1.1.2 以供后续测试,然后重载防火墙配置。最后查看防火墙当前状态:

~]# firewall-cmd --add-masquerade --permanent
~]# firewall-cmd --add-forward-port=port=5022:proto=tcp:toport=22:toaddr=10.1.1.2 --permanent
~]# firewall-cmd --add-forward-port=port=8000:proto=tcp:toaddr=10.1.1.2 --permanent
~]# firewall-cmd --reload
~]# firewall-cmd --list-all
public (active)
    target: default
    icmp-block-inversion: no
    interfaces: ens33 ens34
    sources:
    services: dhcpv6-client ssh
    ports:
    protocols:
    masquerade: yes
    forward-ports: port=5022:proto=tcp:toport=22:toaddr=10.1.1.2
            port=8000:proto=tcp:toport=:toaddr=10.1.1.2
    source-ports:
    icmp-blocks:
    rich rules:

此时检查系统选项,确认 ipv4 转发已启用:

~]# sysctl -a | grep net.ipv4.ip_forward
net.ipv4.ip_forward = 1

启用 DHCP

安装 DHCP 服务

~]# sudo yum install dhcp -y

编辑 /etc/dhcp/dhcpd.conf 文件, 并添加以下配置:

subnet 10.1.1.0 netmask 255.255.255.0 {
    range 10.1.1.150 10.1.1.200;
    option routers 10.1.1.1;
    option subnet-mask 255.255.255.0;
    # 配置一个可用的DNS服务器
    option domain-name-servers 192.168.200.1; 
    # 在虚拟机网卡配置中查看 MAC 地址,给此地址分配固定IP
    host centos-7-user { 
        hardware ethernet 00:0C:29:7B:0B:9C; fixed-address 10.1.1.2;
    }
}

重启服务并打开随开机启动 DHCP:

~]# systemctl restart dhcpd
~]# systemctl enable dhcpd

如果有需要,重启网络服务或者重启主机确认最新网络状态。

~]# systemctl restart network.service

检查客户机网络

客户机通过上述同样方式启用唯一的网卡。

后会发现已经处于刚刚在路由机器上配置的网段并分配了 IP 10.1.1.2。

检查 DNS 服务器是否为路由机上 DHCP 服务中配置的内容:

~]# cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 192.168.200.1

现在可以尝试 ping 一个公网 IP 检查 DNS 和互联网是否连通:

~]# ping baidu.com

路由机上已配置客户机的 SSH 端口转发,现在可以直接通过路由机上的 5022 端口访问客户机。

~]# ssh root@<路由机地址> -p 5022    

配置弱网

这里直接提供一个配置脚本以配置路由机的 WAN/LAN 适配器的出口流量整形。提供了双向丢包 5% 重复 5% 重排 5% 延迟 30ms 上下波动 5ms。可以反复执行此脚本以重载配置。

WAN 出口流量限制了 192.168.200.0/24 源网络 (WAN 卡本身地址) 以及 8000 源端口的数据包。

LAN 出口流量限制了 10.1.1.2/32 目标网络以及 8000 目标端口的数据包。

#!/usr/bin/env bash

wan='ens33'
lan='ens34'

tc qdisc del dev $wan root
tc qdisc add dev $wan root handle 1: htb
tc class add dev $wan parent 1: classid 1:10 htb rate 20000mbit
tc qdisc add dev $wan parent 1:10 handle 10: netem loss 5% duplicate 5% reorder 5% delay 30ms 5ms
tc filter add dev $wan parent 1: protocol ip prio 1 u32 match ip src 192.168.200.0/24 match ip sport 8000 0xffff flowid 1:10

tc qdisc del dev $lan root
tc qdisc add dev $lan root handle 1: htb
tc class add dev $lan parent 1: classid 1:10 htb rate 20000mbit
tc qdisc add dev $lan parent 1:10 handle 10: netem loss 5% duplicate 5% reorder 5% delay 30ms 5ms
tc filter add dev $lan parent 1: protocol ip prio 1 u32 match ip dst 10.1.1.2/32 match ip dport 8000 0xffff flowid 1:10

客户机防火墙打开 8000 端口:

~]# firewall-cmd --add-port=8000/tcp --permanent
~]# firewall-cmd --reload

在客户机中生产一个大文件, 并启用一个简单的 Web 文件服务:

~]# dd if=/dev/zero of=test.file bs=1 count=0 seek=512M

# python 2.x
~]# python -m SimpleHTTPServer 8000
# python 3.x
~]# python -m http.server 8000

通过浏览器下载此文件观察速度。(或者直接使用 iperf 测试网络)

额外还可以通过以下命令检查包在指定网络适配器中命中规则次数:

~]# tc -s filter show dev ens33
~]# tc -s filter show dev ens34

移除流量控制规则:

~] tc qdisc del dev ens33 root
~] tc qdisc del dev ens34 root

以旁路由的方式

如果仅有一个网卡,可以通过结合 firewalld 的 add-forward-port 命令来转发指定外部端口的流量来实现双向流量控制。但是要注意要在同一端口上指定目标和来源端口两个规则:

tc filter add dev $wan parent 1: protocol ip prio 1 u32 match ip src 192.168.200.0/24 match ip sport 8000 0xffff flowid 1:10
tc filter add dev $wan parent 1: protocol ip prio 1 u32 match ip src 192.168.200.0/24 match ip dport 8000 0xffff flowid 1:10

参考

https://www.oreilly.com/library/view/linux-network-administrators/1565924002/ch11.html

https://linuxhint.com/centos7_router/

《创建一台 Linux 路由器设备以模拟弱网环境》有2条评论

发表评论