带路由器、DNS、防火墙和 NAT 的小网络
本实验在 VM 中运行
本实验将前九个实验整合在一起。在命名空间 home(用户侧)与 dmz(服务器侧)
之间,由 VM 自身充当路由器,并由该路由器兼任 DNS 服务器、防火墙和 NAT。
这相当于一台家用路由器所做工作的缩小版。实验时限为 60 分钟,因此可能需要
延长一次时间——请注意,成果会随 VM 一同消失。
目标
连接两个子网,让客户端能按名称找到服务器,只允许 Web 流量通过,使私有网络 能够访问互联网,用数据包验证这一切,最后形成报告。
为什么重要
此前每次只观察一个层次。真实故障往往跨越多个层次——名称能够解析,但被防火墙 拦截;防火墙已经放行,却没有返回路径。亲手从头到尾搭建过一个网络的人,在听到 “无法访问”时会有明确的排查顺序:链路 → 地址 → 邻居 → 路由 → 名称 → 端口 → 防火墙 → 响应。
步骤
- 创建命名空间
home、dmz,以及 vethhome0(home,10.40.1.10/24)↔r-home(根命名空间,10.40.1.1/24)、dmz0(dmz,10.40.2.10/24)↔r-dmz(根命名空间,10.40.2.1/24)。配置两个命名空间的默认路由和根命名空间的ip_forward,使home→dmz能够 ping 通。 - 创建
/root/final/www/index.html,在dmz中启动监听10.40.2.10:80的 Web 服务器(日志写入/root/final/http.log),使home中能够执行curl http://10.40.2.10/。 - 通过
/etc/dnsmasq.d/lab.conf让 dnsmasq 监听10.40.1.1,对web.lab.internal→10.40.2.10作出应答,并将其余查询转发给上游;再通过/etc/netns/home/resolv.conf让home使用该服务器。 - 在
home中执行curl -si http://web.lab.internal/,将响应保存到/root/final/byname.txt。 - 在根命名空间中创建表
inet labfw和带forward钩子的链(策略为drop),只允许established,related以及home→dmz的tcp dport 80,使 Web 可以访问而 ping 无法通过。 - 在表
ip labnat中为10.40.1.0/24添加伪装,并在forward中允许home→uplink 的tcp dport { 80, 443 }。从home执行curl -sI http://archive.ubuntu.com/,将第一行保存到/root/final/internet.txt。 - 在
r-dmz上进行抓包,同时从home再次访问 Web;将能够看到10.40.1.10向10.40.2.10.80发送 SYN 的输出保存到/root/final/capture.txt。 - 将完整规则保存到
/root/final/ruleset.nft,并在/root/final/report.md中写入home_ip=、dmz_ip=、dns=、ping_blocked=四行,以及收到“web.lab.internal 无法打开”的报告时应按什么顺序排查。
参考
- 直接组合前面实验中的命令。第 3、8 个实验的提示尤其有用。
- 要让 dnsmasq 转发给上游,请在
no-resolv之外再写入server=<상류주소>。可通过resolvectl dns enp1s0获取上游地址。 - 防火墙作用于 forward 链。不要修改 VM 自身的 input——否则会阻断评分代理。
nft add rule inet labfw forward iifname "r-home" oifname "r-dmz" tcp dport 80 accept。- 常见错误:在第 6 步遗漏 forward 中对 uplink 方向的放行。仅有 NAT 规则无法越过 forward 的 drop。
两个子网与路由器
创建命名空间 home、dmz,以及 veth home0(home,10.40.1.10/24)↔r-home(根命名空间,10.40.1.1/24)、dmz0(dmz,10.40.2.10/24)↔r-dmz(根命名空间,10.40.2.1/24)。配置两个命名空间的默认路由和根命名空间的 ip_forward,使 home→dmz 能够 ping 通。
将第 8 个实验的第 1 步执行两遍。veth 的 r- 侧保留在根命名空间中。ip -n home route add default via 10.40.1.1、ip -n dmz route add default via 10.40.2.1、sysctl -w net.ipv4.ip_forward=1。
DMZ 中的 Web 服务器
创建 /root/final/www/index.html,在 dmz 中启动监听 10.40.2.10:80 的 Web 服务器(日志写入 /root/final/http.log),使 home 中能够执行 curl http://10.40.2.10/。
ip netns exec dmz setsid python3 -m http.server 80 --bind 10.40.2.10 --directory /root/final/www > /root/final/http.log 2>&1 < /dev/null &。在 index.html 中加入单词 dmz,以后会更容易区分响应。
让路由器兼任 DNS
通过 /etc/dnsmasq.d/lab.conf 让 dnsmasq 监听 10.40.1.1,对 web.lab.internal→10.40.2.10 作出应答,并将其余查询转发给上游;再通过 /etc/netns/home/resolv.conf 让 home 使用该服务器。
在第 4 个实验的配置中加入 server=<상류>,并保留 no-resolv(表示不要从 resolv.conf 读取上游,而要从这一行读取)。执行 systemctl restart dnsmasq。在 /etc/netns/home/resolv.conf 中写入 nameserver 10.40.1.1。验证:ip netns exec home getent hosts web.lab.internal。
按名称访问
在 home 中执行 curl -si http://web.lab.internal/,将响应保存到 /root/final/byname.txt。
ip netns exec home curl -si -m 3 http://web.lab.internal/ > /root/final/byname.txt。-i 会连同响应头一起输出。应当能看到 200 OK 和 index.html 的内容。
只允许 Web 流量通过
在根命名空间中创建表 inet labfw 和带 forward 钩子的链(策略为 drop),只允许 established,related 以及 home→dmz 的 tcp dport 80,使 Web 可以访问而 ping 无法通过。
nft add table inet labfw; nft 'add chain inet labfw forward { type filter hook forward priority 0; policy drop; }'。添加两条规则:ct state established,related accept、iifname "r-home" oifname "r-dmz" tcp dport 80 accept。此时 home 中的 ping 应超时,而 curl 应返回 200。
让家庭网络访问互联网
在表 ip labnat 中为 10.40.1.0/24 添加伪装,并在 forward 中允许 home→uplink 的 tcp dport { 80, 443 }。从 home 执行 curl -sI http://archive.ubuntu.com/,将第一行保存到 /root/final/internet.txt。
直接采用第 8 个实验的第 3 步(ip saddr 10.40.1.0/24 oifname "enp1s0" counter masquerade)。然后在 forward 中添加 iifname "r-home" oifname "enp1s0" tcp dport { 80, 443 } accept。DNS 由路由器自身(dnsmasq)应答,因此不会经过 forward。
使用数据包验证
在 r-dmz 上进行抓包,同时从 home 再次访问 Web;将能够看到 10.40.1.10 向 10.40.2.10.80 发送 SYN 的输出保存到 /root/final/capture.txt。
先执行 timeout 5 tcpdump -i r-dmz -nn -l 'tcp port 80' > /root/final/capture.txt 2>&1 &,再执行 ip netns exec home curl -s http://web.lab.internal/。输出中必须有 10.40.1.10.<포트> > 10.40.2.10.80: Flags [S] 这一行。注意源地址保持不变——内部网络之间没有 NAT。
规则与报告
将完整规则保存到 /root/final/ruleset.nft,并在 /root/final/report.md 中写入 home_ip=、dmz_ip=、dns=、ping_blocked= 四行,以及收到“web.lab.internal 无法打开”的报告时应按什么顺序排查。
nft list ruleset > /root/final/ruleset.nft。报告中的四个值依次为 10.40.1.10、10.40.2.10、10.40.1.1、yes。排查顺序必须包含名称(getent)、路由(ip route get)、防火墙(nft counter)和端口(ss)。