# Virtual Router 學網路 - 從 0 到 100 的 ping ###### tags: `virtual-router`, `arp`, `icmp`, `ping` [TOC] > Source code: https://github.com/kevinbird61/virtual-router > Author: Kevin Cyu, kevinbird61@gmail.com ## 學習目標 1. ping 指令的使用 2. 節點間如何尋找彼此位置 - ARP 3. Routing 4. 網路控制協定 - ICMP (Internet Control Message Protocol) ## 說明 > 參考我們的實驗拓樸: >  * 我們現在從 namespace 的一端 h1 (10.0.0.1) 發起 `ping` 到另一個 namespace h2 (10.0.1.1) * 注意: windows 版本的 ping 與 linux 版本的在封包上有些微的差異存在 (ICMP 的部分) * 此時我們從 ARP 的原理可以知道,ARP 可以用來查找目標節點的 MAC address,讓封包得以正確的傳遞給目標; 而我們的角色此時是 router,因此與 h1 對接的 port1 此時就會收到 h1 發出的 `arp request`, 藉此得知 port1 的 MAC address。 * 注意: 發出 ARP request 的用戶只知道對方的 ip address,但不知道其 MAC address。 * 為何 h1 ping h2 會先詢問 port1 資訊? 原因是在 h1 與 h2 互為不同的 network domain,而此時需要中間的 gateway 來做轉發才能夠將彼此的流量傳輸到正確的位置。 因此我們在建立虛擬拓樸時,便將一條 route 加到各自的 namespace 上來指定當目標匹配這些 rule 時,需要先經過指定的 gateway。使這些 network namespace 能夠依據這條 route 來對這個 gateway 做位置的確認,也就是發出 ARP 的動作。 * 在解釋 router 收到 arp 行為前,我們先分析一下 arp 的封包格式: * arp 為 layer 3 的 protocol,位於 layer 2 (e.g. Ethernet) 之上 * 封包當中主要夾帶的資訊有: * sender ip: 發送者的 IP * sender mac: 發送者的 MAC * target ip: 目標的 IP * target mac: 目標的 MAC * opcode: 決定該 arp packet 的操作種類 (request/reply ...) * 當 opcode 為 arp request 時, target mac 為空,並且 L2 ethernet 的 destination mac address 為 broadcast * 而當目標收到 arp request 後,接著便會送回 arp reply; 此時的 `sender 為目標`, 而 `target 則為 request 發起者`,此時這四個主要資訊都是填寫完畢,並且 L2 ethernet 也是以 unicast 的方式送回去。 * 當我們 router 收到 ARP 時,target ip 為我們 port1 的 IP,因此在收到這個 arp 時,我們便直接回覆 arp reply 給 h1; h1 在收到 arp reply 後便得知這個 gateway 是活著的,因此接下來則會將 ICMP 發出給 port1,讓 port1 來轉發給目標 h2;  * 再根據 routing table 中的內容,來將封包正確轉給正確的 port 做轉送 * 而我們 router (port2) 查找 h2 資訊時,發現 arp cache 沒有該筆資料,因此發出 arp request 來詢問與 port2 相同網域的機器有無 h2 的資訊; h2 再收到 arp request 後一樣回復 arp reply 回來,因此 port2 也更新自己的 arp cache; * 此時 ICMP 的封包再來就能夠將其導向到正確的位置上,完成流量的轉發 ( 反之從 h2 回去的 ICMP echo reply 也是類似的處理流程! )  > 前兩個 packet 用來觸發 arp 更新,被目前實作的版本給 drop 掉,導致 ping 顯示前兩個封包遺失 * 當 host 送 ping 給 port 時,Virtual router 便需要收上來處理 ICMP 封包,將 echo request 更改成 echo reply,以及相關的 mac address 修改完成後再送回去給 Host: * ping  * router's debug message  ## 執行程式 * 執行 `.scripts/create_topo.sh` 來建立我們測試用的網路 * 腳本會建立兩個 tuntap client: `tap0`, `tap1` * 執行我們的 virtual router: `./router -i tap0 tap1` 來讀取這兩個 `tap0` `tap1` 作為我們 router port; 並將收到的封包抓起來做後續處理 * 注意: 預設是將 debug mode 關掉,所以要顯示所有封包資訊請在 router.exe 啟動後輸入 `debug packet` * 透過 `ip netns exec <host>` 來呼叫 namespace 中的 host 執行特定指令,像是流量產生: `ip netns exec h1 ping 10.0.1.1`,從 h1 產生 ping 流量到 h2 上。
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up