我們知道作業系統有分kernel space和user space,user space要透過system call去呼叫kernel space進行I/O的操作,而socket則是專用於網路通訊的system call,使用它宣告一個socket object會回傳一個file descriptor
下面簡單介紹本Project會用到的socket基本API的使用,首先開啟socket就是宣告了一個socket的object
sock = Socket(family, type, proto)
family
family指的是某個通訊協定,例如ipv4, ipv6等等,如果指定ipv4則只對ipv4的通訊協定的封包進行發放,這裡我們使用AF_PACKET,他能直接從網卡讀和寫上面的數據
type
type則是封包數據的格式,主要有SOCK_STREAM和SOCK_DGRAM,分別為TCP和UDP為代表,還有更加原始的格式SOCK_RAW,能自行的組裝數據包,由於我們想監聽所有封包,所以會使用SOCK_RAW
proto
Proto則是protocol的意思,通常預設為0,那麼我們的應用要監聽所有封包,所以設定為0x0003來監聽所有ethernet上的封包
雖然Socket提供許多參數讓開發人員只要專注在某個協議的某個應用,但是這系列的文章希望能了解傳進網卡最原始的封包是如何組成的,上述設定能達到我們的目的,記下來說一下socket常用的API。
bind((addr, port))
需監聽和發送的地址和port,地址若為0.0.0.0則代表所有,也能監聽網卡
recv(1024)
如果有封包進來,則kernel space響應這個函數,讓我們的應用程式可以對封包進行處理,若沒有則會被block在這,函數回傳的是小於等於1024長度的string,看封包大小
send(packet)
packet就是我們做成的封包,在30天的後半段會教大家怎麼做自己的封包,怎麼算checksum,socket會根據封包裡的mac address和ip address進行路由
除了上述這些API,還有很多很多,有興趣的讀者能再深入研究
系列的成果將會放在這:https://github.com/kaichiachen/pytcpdump
文章配合著程式碼有助於學習 :)