問題: 當使用不同來源位址產生封包時,不會遵守為將 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 的路由機制不支援來源路由,這解釋了您所描述的行為。