问题: 当使用不同源地址生成数据包时,不会遵守为将 L4 流量路由出特定接口而构建的 ip 规则。
概述 我想生成源地址与主机地址不同的数据包。为了实现这一点,我使用 python 的包 Scapy。注意:我的目标是发送 DNS 流量,但是我无法找到一个简单的解决方案来欺骗 DNS 请求中的源地址,因此我只是在端口 53 处生成带有 src 和 dst 地址的 UDP 数据包,相信这仍然有效,因为我目前只测试 L3 和 L4,而不是实际的 DNS 协议。这是我的脚本
#!/usr/bin/python3
# The following is designed to generate a packet with a different source address
import sys
from scapy.all import *
def main():
S = "10.0.26.122" # spoofed source IP address
D = "10.0.26.123" # destination IP address
SP = 53 # source port
DP = 53 # destination port
payload = "This is a fake message" # packet payload
spoofed_packet = IP(src=S, dst=D) / UDP(sport=53, dport=53) / payload
send(spoofed_packet)
#Entry point
main()
在运行脚本之前,我的路由表如下所示:
# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.104.8.1 0.0.0.0 UG 101 0 0 ens192
10.0.21.0 0.0.0.0 255.255.255.0 U 104 0 0 ens256
10.0.26.0 0.0.0.0 255.255.255.0 U 0 0 0 ens224
10.0.27.0 0.0.0.0 255.255.255.0 U 102 0 0 ens193
10.0.28.0 10.0.29.1 255.255.255.0 UG 100 0 0 ens161
10.0.29.0 0.0.0.0 255.255.255.0 U 100 0 0 ens161
10.104.8.0 0.0.0.0 255.255.255.0 U 101 0 0 ens192
10.212.134.0 10.104.8.1 255.255.255.0 UG 101 0 0 ens192
192.168.122.0 0.0.0.0 255.255.255.0 U 0 0 0 virbr0
这是ip接口
# ip -br a
lo UNKNOWN 127.0.0.1/8
ens161 UP 10.0.29.122/24
ens192 UP 10.104.8.122/24
ens193 UP 10.0.27.122/24
ens224 UP 10.0.26.122/24
ens256 UP 10.0.21.122/24
virbr0 DOWN 192.168.122.1/24
virbr0-nic DOWN
ip_vti0@NONE DOWN
当我运行脚本时./packet-gen.py "10.0.26.122" "10.0.26.123"
它起作用了。这是因为我还没有构建我的 ip 规则/单独的路由表。我在主机 (10.0.26.122) 和远端主机 (10.0.26.123) 上执行 tcpdump,并且看到正在发送的 UDP 数据包。我还进行了测试dig www.google.com @10.0.26.123
,看到正在执行的实际 DNS 请求并获得响应。
现在问题来了。我想删除主表中的路由条目,然后仅根据端口号进行路由。为此,我运行以下命令,首先删除 10.0.26.0/24 的路由条目。
# ip route del 10.0.26.0/24 dev ens224
# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.104.8.1 0.0.0.0 UG 101 0 0 ens192
10.0.21.0 0.0.0.0 255.255.255.0 U 104 0 0 ens256
10.0.27.0 0.0.0.0 255.255.255.0 U 102 0 0 ens193
10.0.28.0 10.0.29.1 255.255.255.0 UG 100 0 0 ens161
10.0.29.0 0.0.0.0 255.255.255.0 U 100 0 0 ens161
10.104.8.0 0.0.0.0 255.255.255.0 U 101 0 0 ens192
10.212.134.0 10.104.8.1 255.255.255.0 UG 101 0 0 ens192
192.168.122.0 0.0.0.0 255.255.255.0 U 0 0 0 virbr0
该条目被删除。如果我再次运行我的脚本,它就不起作用。挖掘请求也失败。这是预期的,因为主内核路由表中没有 L3 路由。
为了在 L4 上路由,我首先创建了一个新的 ip 路由表以通过 ens224 发送所有流量:
# ip route add table 53 0.0.0.0/0 dev ens224
然后,我创建一个 ip 规则来捕获使用端口 53 的任何流量,并发送我的自定义表 53。
# ip rule add ipproto udp dport 53 lookup 53
我还为 rp_filter 创建了一个特殊的 sysctl 规则,过于放松严格的反向路径转发规则
# sysctl -w "net.ipv4.conf.ens224.rp_filter=2"
为了检查我的工作,我看到以下内容:
# ip route list table 53
default dev ens224 scope link
# ip rule list
0: from all lookup local
32765: from all ipproto udp dport 53 lookup 53
32766: from all lookup main
32767: from all lookup default
# ip route get 10.0.26.123 ipproto udp dport 53
10.0.26.123 dev ens224 table 53 src 10.0.26.122 uid 0
cache
# ip route get 10.0.26.123
10.0.26.123 via 10.104.8.1 dev ens192 src 10.104.8.122 uid 0
cache
最后一条命令显示,默认情况下,如果通信不是 dns,则使用默认路由。
为了测试这一点,我首先尝试 ping 10.0.26.123。它失败了,这是预期的。现在我尝试执行挖掘请求dig www.google.com @10.0.26.123
,并且它有效。 dig 请求在进入主表之前符合 ip 规则并被适当路由。我看到流量通过 tcpdump (10.0.26.123) 到达服务,并且来自我的主机 (10.0.26.122)。
现在我尝试再次运行我的 scapy 脚本,但什么也没发生。即使与主机具有相同的源地址,我的主机或服务器上的 tcpdump 中也没有任何内容。我尝试更改源地址,没有更改,什么也没有。如果我在主表中添加回 10.0.26.0/24 的主 L3 路由,scapy 脚本将再次运行。我在这里缺少什么?为什么我生成的流量不遵守我创建的 IP 规则集?
答案1
Scapy 不使用操作系统路由机制,而是使用自己的路由表(对象),在 Scapy 启动时(或每当调用方法时)conf.route
从操作系统路由表同步。conf.route.resync()
Scapy 的路由机制不支持源路由,这解释了您所描述的行为。