ref: https://www.hwchiu.com/ping-implementation.html
本篇文章是難得的自產文章,該文章分享一下自己觀察不同 ping 指令與不同發行版本下的實作方式,主要探討的點是 ICMP 封包是如何產生的。
就我目前認知,目前至少有三種常見方式來設定 ping 指令讓其能夠順利收送 ICMP 封包。
常見的 TCP/UDP 應用程式實際上都是讓 Kernel 幫忙處理底層的 L3/L4 封包,使用者的應用程式則是專注於資料的交換與處理,簡單的說法就是專心處理 L7 資料。
但是 ICMP 封包不同於上述的 TCP/UDP 封包,一種方式就是透過 RAW Socket 的形式自行去拼湊組裝 ICMP 格式,自行處理一切封包的處理。
RAW Socket 本身也不允許每個使用者都能輕易開啟,必須要有相關的權限才可以執行,因此一種 PING 的實作方式就是透過 SetUID 的方式,讓所有能夠執行 ping 指令的使用者會短暫瞬間提權變成 Root 的身份
也因為是 Root 就可以順利的開啟 RAW Socket。
SetUID 強大且方便,簡簡單單就可以讓使用者瞬間變成 Root,但是也因為簡單好像就安全角度來看會覺得不太嚴謹,畢竟我想要的只是一個能夠開啟 RAW Socket 的權限,你去把整個 Root 都送給我。
因此第二種實作方式就是透過 Linux Capability 來達到更細緻化的權限控管,讓任何可以執行 ping 指令的使用者都可以短暫獲得 cap_net_raw 的權限,最終順利的開啟 RAW Socket
而第三種方式則是跳脫的權限的概念,與其透過 RAW Socket 來自行打造 ICMP 封包,不如讓 Linux Kernel 幫忙處理 ICMP 封包,ping 的程式只要跟 Kernel 要求建立一個基於 ICMP 協定的 socket 即可。
透過第三種方式最終可以達到 setuid-less 的架構,ping 的應用程式再也不需要任何的特殊權限,每個使用者都可以順利執行來收送 ICMP 封包。
文章內會針對三種方式進行實驗跟觀察,對 PING 指令有興趣別忘了參考看看
udp封包 在 矽谷牛的耕田筆記 Facebook 八卦
ref: https://javascript.plainenglish.io/what-is-http-3-and-why-does-it-matter-cb7d7b4b600f
這篇文章簡單的敘述何謂 HTTP/3,主要探討 HTTP/3 到底跟 HTTP/1, HTTP/2 的差異是什麼
HTTP/3,也可以稱為 HTTP ove QUIC,這對過往的 HTTP 來說帶來了巨大的改變,因為 HTTP/{1,2} 都是基於 TCP 來傳輸封包,而 HTTP/3 則是仰賴 QUIC (Google 於 2012 所開發的協定,底層基於 UDP)。
TCP 目前普遍被使用到各式各樣的網路應用程中,而 TCP 本身的設計到今日來看也是有不少為人詬病的地方,譬如說 TCP 當初發明的時空背景與當前網路環境已經不同,譬如網際網路中的頻寬大小等
所以後續也有不少的演算法想要針對 TCP 來進行改善,譬如 Congestion Control 相關就有不少演算法可以選擇。
另外一個更直接簡單的就是直接跳過 TCP,直接使用 UDP 做為底層傳輸協定並且於應用層級重新打造一個如 TCP 一樣可信賴的傳送方式,這也是 QUIC 這個協定的基本概念。
透過 QUIC 的幫助,作者提到 HTTP/3 能夠得到下列的好處
Faster request multiplexing
HTTP/2 以前, 瀏覽器每次都只能對 Server 發送一個 Request,這導致網頁讀取速度緩慢,而 HTTP/2 則試圖改善這個機制,不過 TCP 本身的設計就不是針對這類型的使用
譬如眾多封包中只要有一個失敗, TCP 本身就會針對所有發送的 Request 去進行一個重送的動作來確保封包傳輸正常。
HTTP/3 因為不再使用 TCP 為底層協定而是 UDP,所以當上述情況發生時,也只需要針對失敗的 Request 進行重送即可,也因為此協定帶來的好處, HTTP/3 的表現會相較於之前版本來得更快更穩。
Faster Encryption
HTTP/3 允許最初的 HTTP Request 以加密的形式去傳送。過往傳統的 HTTPS 封包傳輸過程中,最初的握手階段交換資訊時,這些還是基於非加密的形式,要等到握手完畢後才可以能力將接下來的資料進行加密。
而 QUIC 本身可以針對 Initial Connection 進行 TLS 的處理,這使得 HTTP/3 於加密方面可以更順利也更簡單。
文章後半部分提到關於目前 HTTP/3 實作的部分,有興趣的人可以參考參考原文
udp封包 在 純靠北工程師 Facebook 八卦
#純靠北工程師5cy
----------
小弟公司做iot的,從設備端到資料倉儲中心到手機remote app到串ERP都有做,最近公司遇到奇葩客戶,對方自己養了一個「寫了十年web的工程師」,然後叫我們做設備跟app就好,中間的溝通server該工程師堅持要自己寫,且業主要求在一季內完成所有項目,開會跟對方解釋如果對方工程師要從頭開始寫起要處理一大堆兩邊對接的問題等等各種雞毛蒜皮的事,建議用本公司既有的系統下去改商業邏輯的部分就好,結果對方工程師不斷跳針:「啊不就是mqtt跟http兩邊資料互傳就好,就是用api資料丟來丟去而已嘛,雖然我沒寫過但我不覺得這很難啊,只要知道api要傳哪些資料我也可以啦」各種貶低iot這行的言論,
當場我就想走人跟老闆說這案不要接,他說他行那讓他自己上......
同樣是碼農,隔行如隔山啊,有必要這樣把人家的工作講的一文不值嗎?
何況我還沒講到可能還會碰到要處理跟某些設備互傳udp封包指令的事,從頭到尾我看這傢伙只懂http跟websocket,只有一季時間要從零做到完到底自信哪來的,真的好想叫老闆放生這公司讓他們自己踩雷後再來求人......
----------
💖 純靠北官方 Discord 歡迎在這找到你的同溫層!
👉 https://discord.gg/tPhnrs2
----------
💖 全平台留言、文章詳細內容
👉 https://init.engineer/cards/show/6946
udp封包 在 6 07 UDP封包格式 的八卦

... <看更多>
udp封包 在 [問題] UDP指定IP接收封包- 看板C_and_CPP - 批踢踢實業坊 的八卦
開發平台(Platform): (Ex: VC++, GCC, Linux, ...)
Windows VC++
Linux GCC
問題(Question):
能否建立一UDP連線, 可以接收指定IP的封包
我嘗試Windows的寫法, 也試過Linux的寫法, 但一直都沒有辦法做到.
程式碼(Code):(請善用置底文網頁, 記得排版)
[Windows Code]
來源 https://ppt.cc/Gwcj
SOCKET RecvSocket;
unsigned short Port = 27015;
sockaddr_in RecvAddr;
RecvSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (RecvSocket == INVALID_SOCKET) {
wprintf(L"socket error %d\n", WSAGetLastError());
return 1;
}
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
iResult = bind(RecvSocket, (SOCKADDR *) &RecvAddr,
sizeof (RecvAddr));
if (iResult != 0) {
wprintf(L"bind error %d\n", WSAGetLastError());
return 1;
}
...
若紅色的地方換成下面
RecvAddr.sin_addr.s_addr = inet_addr("192.168.107.100");
則會印出黃色的部份
bind error 10049
問題1: 這邊為什麼會出現這種錯誤? 是不能bind這種ip嗎?
[Linux Code]
struct sockaddr_in RecvAddr;
struct sockaddr_in CliAddr;
int lenCli = sizeof(CliAddr);
int len;
char buffer[4096];
int sock = socket(AF_INET, SOCK_DGRAM, 0);
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("192.168.107.100");
int rc = bind(sock, (struct sockaddr*)&RecvAddr, sizeof(RecvAddr));
if(rc < 0)
{
perror("bind error:");
return 0;
}
memset(&CliAddr, 0, sizeof(CliAddr));
len = recvfrom(sock, buffer, 4096, 0, (struct sockaddr*)&Cliaddr,
&lenCli);
if(len < 0)
{
perror("recvfrom error:");
return len;
}
....
問題2:
如果紅色的部份是
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
可以收到封包, 但如果如紅色那樣子指定IP後,
就收不到封包了,
請教各位大大, 究竟要如何用才能讓UDP接收指定IP的封包? 謝謝
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 36.225.28.113
※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1400033354.A.0E8.html
... <看更多>