我是個菜鳥,這是我第一次嘗試內核網路。我正在嘗試在兩個介面之間創建一座橋tap
,並嘗試發送流量。它更像是實驗,而不是為了任何特定目的。
$ brctl showstp br0
br0
bridge id 8000.46846e0c0ff9
designated root 8000.46846e0c0ff9
root port 0 path cost 0
max age 20.00 bridge max age 20.00
hello time 2.00 bridge hello time 2.00
forward delay 15.00 bridge forward delay 15.00
ageing time 300.00
hello timer 1.98 tcn timer 0.00
topology change timer 0.00 gc timer 115.04
flags
tap1 (1)
port id 8001 state forwarding
designated root 8000.46846e0c0ff9 path cost 100
designated bridge 8000.46846e0c0ff9 message age timer 0.00
designated port 8001 forward delay timer 10.34
designated cost 0 hold timer 0.98
flags
tap2 (2)
port id 8002 state forwarding
designated root 8000.46846e0c0ff9 path cost 100
designated bridge 8000.46846e0c0ff9 message age timer 0.00
designated port 8002 forward delay timer 0.00
designated cost 0 hold timer 0.98
flags
我已經創建了橋樑 br0
,tap1
並tap2
添加了兩者。我有一個程式將 ARP 封包注入tap1
使用libpcap
. Wireshark 正確顯示進入的資料包tap1
。但是,沒有資料包出現在 處tap2
。我嘗試在 ebtables 中添加以下規則:
sudo ebtables -I INPUT --log --log-level debug
日誌中沒有顯示任何資料包。我將不勝感激任何意見。
編輯:新增更多資訊。注入假包確實是應用。我的目的是完全用軟體且無需虛擬機器來模擬封包如何透過 Linux 核心堆疊轉送。我沒有創建任何新的網路命名空間。也許這就是問題所在?
我只有兩個進程。 「讀取」進程有一個開啟的檔案描述符tap2
,並且不斷嘗試從中讀取。寫入進程開啟一個檔案描述符tap1
並等待使用者提示發送 ARP 查詢。 ARP 查詢具有隨機來源 IP 位址。來源MAC位址設定為 的MAC位址tap1
。這是 tcpdump 的輸出:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tap1, link-type EN10MB (Ethernet), capture size 262144 bytes
^[[A07:19:57.752990 ARP, Request who-has google-public-dns-a.google.com tell 0.0.248.17, length 28
0x0000: ffff ffff ffff ba9c 0589 16ad 0806 0001
0x0010: 0800 0604 0001 ba9c 0589 16ad 0000 f811
0x0020: 0000 0000 0000 0808 0808
我已經配置了tap1
並且tap2
沒有IP位址。這可能是問題所在嗎?
brctl addbr br0
ip tuntap add name tap1 mode tap
ip tuntap add name tap2 mode tap
brctl addif br0 tap1
brctl addif br0 tap2
ifconfig tap1 0.0.0.0 up
ifconfig tap2 0.0.0.0 up
ifconfig br0 10.0.1.1 netmask 255.255.255.0 broadcast 10.0.1.255
ip link set br0 up
ip link set tap1 up
ip link set tap2 up
根據答案,我檢查了將各種應用程式附加到tap2
.我注意到這一點:當沒有應用程式使用tap1
or時tap2
,兩個介面都沒有設定 LOWER_UP 標誌。
4: br0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff
25: tap1: <NO-CARRIER,BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast master br0 state DOWN mode DEFAULT group default qlen 500
link/ether ba:9c:05:89:16:ad brd ff:ff:ff:ff:ff:ff
26: tap2: <NO-CARRIER,BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast master br0 state DOWN mode DEFAULT group default qlen 500
當我啟動應用程式時,LOWER_UP 標誌被設定:
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff
25: tap1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP mode DEFAULT group default qlen 500
link/ether ba:9c:05:89:16:ad brd ff:ff:ff:ff:ff:ff
26: tap2: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP mode DEFAULT group default qlen 500
link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff
很抱歉這篇文章太長了,我只是希望有足夠的資訊來理解這個問題。
答案1
以防萬一,因為你說你是個菜鳥:tun(第 3 層)或 tap(第 2 層)介面是應用程式的網路介面端點,應用程式可以從此網路介面讀取和寫入封包。您創建的內容ip tuntap add ...
或過時的內容tunctl
是持久名稱對於此類端點,您通常仍會運行該應用程序,並且除非您運行該應用程序,否則它不會執行任何操作。
由於應用程式與網路介面互動是設計問題,因此無需使用第三方應用程式「注入」資料包,除非您指的是「注入」我所描述的這種正常互動。
另外,如果您想嘗試網絡,我建議您使用網路命名空間和veth對。基本上,您可以在計算機上設定許多虛擬計算機,這些計算機可以模擬網路上真實計算機之間的通訊。
因此,如果您想這樣做,並且不想使用自己的應用程式建立和接收資料包,則不需要 tun/tap 介面。
也就是說,我只是測試了您的設置,略有不同,因為您沒有說明您使用什麼來“注入”數據包:我使用了兩個socat
s 來創建分接端點tap0a
和tap1a
,然後我橋接它們,並在中使用了另外兩個socat
s兩個不同的命名空間為我創建正確的資料包。它們需要位於不同的命名空間中,因為本地資料包將始終通過環回傳遞lo
。
正如預期的那樣,橋接分路設備運作得很好。
所以我認為問題出在您注入的資料包中:錯誤的乙太網路位址,或沒有廣播。tcpdump -xx ...
當您注入 ARP 封包時,請使用輸出編輯您的問題。
或者您可能想建立網路命名空間並橋接兩個 veth 對的兩個端點?這樣就簡單多了。
編輯
ARP 封包看起來不錯。似乎沒有連接到 的應用程式tap2
。如果這樣做ip link
,您不應該看到 的LOWER_UP
標誌tap2
。猜測:網橋偵測到裝置僅部分啟動,因此不會向該連接埠發送資料包。
tap
嘗試用that替換它有連接到它的應用程序,例如
sudo socat TUN:10.0.2.2/24,tun-name=tapx,tun-type=tap,iff-up - | hexdump -C
(該10.0.2.2/24
位址不會執行任何操作,但socat
如果您不指定位址,則該位址將無法運作),並在另一個終端中
sudo ip link set tapx master br0
(替換brctl addif
),然後多次注入資料包,看看是否在第一個視窗中得到十六進位轉儲。也要檢查LOWER_UP
與ip link show dev tapx
.
順便說一句,ifconfig
已經brctl
過時了。使用ip
andbridge
代替。
不為網橋連接埠分配 IP 位址並不重要,因為網橋連接埠沒有 IP 位址(如果他們在被橋奴役之前被分配了一些,他們就會被忽略)。參見例如這裡。
答案2
我為此苦苦掙扎,並認為我已經找到了解決方案。或者,至少,更好地了解正在發生的事情。
重要的是要記住,將資料包傳送到接收端(“RX”)的 Tap 介面的唯一方法是將該資料包寫入套接字描述符由打開水龍頭的進程創建(通過open("/dev/net/tun",...)
和ioctl
)。一次只有一個進程可以擁有該檔案描述符。如果一個 Tap 設備已打開,並且另一個進程嘗試重新開啟另一個同名的 Tap 設備,則該系統呼叫將失敗。
因此,當您有任何其他進程(例如wireshark)時,打開原始套接字然後綁定那至tap0
,它只能寫入流量出去系統的(從核心的角度)。也就是說,wireshark 應該會增加TX
的計數器tap0
,並且只有RX
封包會被轉送到橋接介面。
您可以檢查每個計數器,例如:
#!/bin/bash
for if in tap{0,1}; do
stats=/sys/class/net/$if/statistics/
rx=$(cat $stats/rx_packets)
tx=$(cat $stats/tx_packets)
echo "$if: rx=$rx, tx=$tx"
done
輸出如下:
tap0: rx=0, tx=6
tap1: rx=0, tx=5
因此,根據您的具體情況,我懷疑問題出在這裡:
我有一個使用 libpcap注入
ARP
資料包的程式。tap1
Wireshark 正確顯示進入的資料包tap1
。但是,沒有資料包出現在 處tap2
。
如何將 ARP 封包注入到 tap1 中?我假設wireshark沒有呼叫fd = open("/dev/net/tun", ...)
and ioctl(fd, TUNSETIFF, ...)
,因此發送的資料包將是TX,因此不會橋接。
tap0
您將需要打開將資料包寫入 的文件描述符的程序,tap0
以使這些資料包在 上轉發br0
並顯示在 上tap1
。