diff --git a/.github/workflows/cd.yaml b/.github/workflows/cd.yaml
index e7e8ac4ce75e..86c9803000e6 100644
--- a/.github/workflows/cd.yaml
+++ b/.github/workflows/cd.yaml
@@ -42,6 +42,11 @@ jobs:
git add .
git commit -m "Update og image"
git push
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: og-image
+ path: ${{ github.workspace }}/assets/img/og
build_and_deploy:
runs-on: ubuntu-latest
@@ -59,6 +64,11 @@ jobs:
restore-keys: |
${{ runner.os }}-gems-
+ - uses: actions/download-artifact@v4
+ with:
+ name: og-image
+ path: ${{ github.workspace }}/assets/img/og
+
# Use GitHub Deploy Action to build and deploy to Github
# For latest version: `jeffreytse/jekyll-deploy-action@master`
# This is a specific version for supporting og:image with libpng pre installed
diff --git a/_posts/container/2024-02-12-container-docker-to-k8s.md b/_posts/container/2024-02-12-container-docker-to-k8s.md
index 2203754b61df..6307ef5e3f6b 100644
--- a/_posts/container/2024-02-12-container-docker-to-k8s.md
+++ b/_posts/container/2024-02-12-container-docker-to-k8s.md
@@ -155,6 +155,9 @@ docker 有自己內建的 dns server, 這也解釋了為什麼我們可以單純
而你每一次呼叫 "web" service 的時候,dns server 都要決定要給你哪一個 ip 對吧\
所以負載平衡這段其實是由 docker 內建的 dns server 幫你做掉了
+> 有關 DNS load balancing\
+> 可參考 [重新認識網路 - 從基礎開始 \| Shawn Hsu](../../network/networking-basics)
+
你說可是上面我們還是使用了 nginx 阿\
那是因為每一個 replica service 都使用了相同的 port number(這個會造成 error), 我們需要一個統一的進入點存取\
所以這裡才使用了 nginx
diff --git a/_posts/network/2022-04-28-network-osi.md b/_posts/network/2022-04-28-network-osi.md
index 78004c12669f..61e5269cbc32 100644
--- a/_posts/network/2022-04-28-network-osi.md
+++ b/_posts/network/2022-04-28-network-osi.md
@@ -71,7 +71,7 @@ OSI 七層模型是由 [國際電信聯盟電信標準化部門 - ITU-T](https:/
常見的協議如 [TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) 以及 [UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol) 都是跑在傳輸層之上的協議
-
+> 詳細的討論可以參考 [重新認識網路 - 從基礎開始 \| Shawn Hsu](../../network/networking-basics)
## Network Layer - 3
網路層主要是作 routing 的功能\
@@ -117,7 +117,7 @@ hop 這個東西簡單講就是,`經過的中繼站點個數`, 它也可以用
layer 3 switch 以及 IP 分享器 都是網路層的設備
除此之外,[Internet Protocol IP](https://en.wikipedia.org/wiki/Internet_Protocol) 也是跑在網路層的上的協議
-
+> 詳細的討論可以參考 [重新認識網路 - 從基礎開始 \| Shawn Hsu](../../network/networking-basics)
## Data Link Layer - 2
資料連結層為了提供 [connectionless-mode](https://en.wikipedia.org/wiki/Connectionless_communication) 以及 connection-mode,所以它必須提供了一系列的連線建立、維護\
diff --git a/_posts/network/2024-05-07-network-basics.md b/_posts/network/2024-05-07-network-basics.md
new file mode 100644
index 000000000000..f56992c612c2
--- /dev/null
+++ b/_posts/network/2024-05-07-network-basics.md
@@ -0,0 +1,464 @@
+---
+title: 重新認識網路 - 從基礎開始
+date: 2024-05-07
+description: 本篇文章將會涵蓋所有網際網路的基礎,包含 DNS, TCP, UDP, TLS。其中會使用 Tcpdump, Wireshark 等工具實際觀察
+categories: [network]
+tags: [tcp, udp, ssl, tls, dns, nc, tcpdump, wireshark, broadcast, load balance, ip, telnet, multicast, unicast]
+redirect_from:
+ - /network/networking-basics/
+math: true
+---
+
+# DNS - Domain Name System
+Domain Name System 是一個分散式的系統,用於紀錄網域名稱和 IP 位址之間的關聯\
+基本上現今我們在瀏覽網站的時候,多半是使用所謂的 domain name 上網的\
+比方說 `google.com`, `facebook.com`
+
+對於人類來說,這是比較容易理解的\
+IP address 則是方便於電腦進行解析的,但卻是不容易理解\
+因此 DNS 的作用就是將 IP address 轉換成網域名稱
+
+本質上 DNS 分散式架構有助於提昇整體吞吐量\
+包含單一節點失效,效能問題(可參考 [資料庫 - 最佳化 Read/Write 設計(硬體層面) \| Shawn Hsu](../../database/database-optimization-hardware))
+
+## DNS Server Categories
+![](https://qph.cf2.quoracdn.net/main-qimg-5ed6b5866ff2e2d1d26095a49aa4c25e)
+> ref: [What is a DNS root server and what do they do?](https://www.quora.com/What-is-a-DNS-root-server-and-what-do-they-do)
+
+基本上分為三種類型
+
++ Root DNS Server
+ + 這些伺服器是整體網路的最高階,共有 13 個組織負責管理
+ + Root server 不會直接回 ip address, 它會告訴你誰擁有這些資訊,然後你去找 `TLD DNS Server`
++ Top-level Domain DNS Server
+ + 高階網域如 `com`, `org`, `edu` 等都會紀錄在 Top-level Domain DNS Server 中
+ + 同樣它也不會直接回 ip address, 它會告訴你誰有這些資訊,然後你再去找 `Authoritative DNS Server`
++ Authoritative DNS Server
+ + 到這層就會真的給你 ip address 了
+
+所以每次你的查詢都是從高階到低階\
+這樣很慢嘛,所以也會有 caching 的機制在裡面
+
+## DNS Load Balancing
+現今的服務器通常都是分散式系統,這就意謂著一個 domain name 可能會對到很多台實體伺服器\
+那麼當你存取的時候,是哪一台伺服器需要回應你呢
+
+DNS 通常會回應一連串的 IP address\
+client 通常會取第一個 ip 使用\
+每次 DNS 回應的時候,server 會輪流改變 ip address 的順序\
+所以同一台伺服器就不會太操勞
+
+這樣就可以做到基本的 load balancing
+
+## nslookup
+這個指令可以查詢網域名稱對應的 IP address\
+舉例來說
+
+```shell
+$ nslookup google.com
+Server: 127.0.0.53
+Address: 127.0.0.53#53
+
+Non-authoritative answer:
+Name: google.com
+Address: 172.217.163.46
+Name: google.com
+Address: 2404:6800:4012:4::200e
+
+```
+
+不熟悉 command line 操作也可以使用類似 [NsLookup.io](https://www.nslookup.io/) 等網站來查詢
+
+# Socket
+> In UNIX, Everything is a File
+
+事情還得要從作業系統說起\
+UNIX 的設計哲學是,Everything is a File\
+每個東西都是檔案,什麼意思?\
+檔案不就是檔案嗎? 那麼網路,印表機這些也算檔案嗎?\
+依照作業系統的邏輯,如果要詳細區分這些東西為各種不同的類別,那麼實作起來將會無比困難\
+因此,就算是印表機這種東西,底層實作也會將它視為是 **檔案**
+
+建立網路連線,它分成大約兩步驟
+1. 建立 socket(i.e. file descriptor),建立好一個對接的端口
+2. 建立連線(並且透過 socket 進行資料的傳輸)
+
+而 socket 就是那個 **檔案**\
+每個應用程式都擁有自己的 socket 接口\
+你可以使用 [lsof](https://linux.die.net/man/8/lsof) 這個指令查看當前 internet file descriptor 的狀況\
+執行 `$ sudo lsof -i` 你會看到類似這張圖的輸出
+![](/assets/img/posts/lsof.png)
+可以很清楚的看到,chrome 瀏覽器開了許多的 socket
+
+> 你應該還會看到其他應用程式,像我的還有 telegram, docker ... etc.
+
+
+
+socket 有沒有數量限制呢? 或者說比較 general 一點\
+file descriptor 有沒有上限?\
+我想答案很明顯是有的
+
+```shell
+$ ulimit -n
+1024
+```
+
+> 可參考 [man ulimit](https://linuxcommand.org/lc3_man_pages/ulimith.html)
+
+# IP - Internet Protocol
+提供 `主機` 之間的通訊,但不提供任何保障
+
++ 不保證送達目的地
++ 不保證會依序送達
+
+# Process Communication - A High Level View
+兩個不同的 process 要透過 network 的方式進行溝通\
+離不開兩個觀念,送資料([Transport-layer Multiplexing](#transport-layer-multiplexing))與收資料([Demultiplexing](#demultiplexing))
+
+## Transport-layer Multiplexing
+將資料與 header 封裝在一起透過 [Socket](#socket) 往下丟給網路層\
+而 header 包含了一些下層需要知道的事情\
+比方說你要送到哪裡,要給誰\
+舉例來說 sender/receiver 的 ip 跟 port
+
+換言之,如果 ip port 都一樣,那代表這兩個連線是一樣的
+
+> port 1024 以後都可以隨意用,1 ~ 1023 不能使用
+
+> 為什麼要有 sender 的資料? 因為要知道資料要送回哪裡
+
+## Demultiplexing
+將網路層上來的資料分送到正確的 [Socket](#socket) 端口\
+然後在根據 header 裡面的內容,送到正確的地方
+
+# TCP - Transmission Control Protocol
+TCP 是建立在 [IP](#ip---internet-protocol) 之上的協議\
+IP 是專注在 **主機** 之間的通訊,而 TCP 則是專注在 **行程(process)** 之間的通訊
+
+> 可參考 [RFC 793](https://datatracker.ietf.org/doc/html/rfc793)
+
+TCP 相比 [IP](#ip---internet-protocol) 額外提供了
++ 可靠性傳輸(保證送達以及保證順序送達)
++ 壅塞控制(congestion control)
+
+> 有關傳輸層的討論可以參考 [重新認識網路 - OSI 七層模型 \| Shawn Hsu](../../network/networking-osi)
+
+## Why Handshake is Important
+TCP 是可靠傳輸,所以它需要花一點時間建立可靠連線\
+為什麼要花時間建立連線?
+
+試想線上會議的情況下,當你加入會議,你可能會先確保你的麥克風、喇叭是不是正常的\
+確定對方聽的到你的聲音,然後你也聽的到對方的,才會開始開會對吧\
+這就是一個確保連線成功的機制
+
+結束會議也一樣\
+跟對方說你要下線了,對方也會跟你說要下線了\
+雙方都要認知道對方要下線,並且同意\
+才可以關閉連線
+
+> TCP 在 [RFC 793](https://datatracker.ietf.org/doc/html/rfc793) 並沒有定義需要做 結束會議的握手\
+> 但是 [RFC 6824](https://datatracker.ietf.org/doc/rfc6824/) 裡面有定義而且 tcpdump 的結果有時候有出現\
+> 就在這裡提一下
+
+你可能會覺的什麼都要 double check 是一件很麻煩的事情\
+但沒有進行這個確保的情況下,你可能會漏掉對方的資訊\
+而這樣就不是可靠性傳輸了
+
+對應到網路世界,這個過程稱之為握手\
+TCP 在以下情況會做握手
+1. 建立連線 - [Three-way Handshake](#three-way-handshake)
+2. 結束連線 - [Four-way Handshake](#four-way-handshake)
+
+
+
+需要注意的是\
+TCP server 會需要 **2 個 socket** 來處理連線\
+為什麼呢
+
+我們說過,一個 connection 背後代表著一個 unique 的 [Socket](#socket)\
+TCP 是可靠性傳輸協定,每一個獨立的連線傳輸都有一個 socket\
+也就是說會有若干個 socket
+
+如果說每一個連線的 socket 都不一樣\
+那麼你需要一個統一的連接進入點來處理不同的 connection\
+這也就是為什麼 TCP server 會需要 2 個 socket 來處理連線
+
+一個是主要進入點的 socket\
+另一個則是每個 client 獨立的 socket\
+所以是兩個
+
+## Three-way Handshake
+![](https://www.techopedia.com/wp-content/uploads/2023/03/ad900dc1-ad94-4c7b-a3f8-154ad27c35f1.png)
+> ref: [Three-Way Handshake](https://www.techopedia.com/definition/10339/three-way-handshake)
+
+所以基本上 TCP 三方交握就是一個初始化 say hello 的流程\
+確認你已經準備好要收訊息了 我也準備好要發訊息了這樣
+
+![](/assets/img/posts/tcpdump1.png)
+
+> 前情提要 tcpdump flag
+>
+> |flag|shortened|description|
+> |S|syn|synchronize 同步|
+> |.|ack|acknowledge 確認|
+> |F|fin|結束連線|
+> |P|push|傳送資料|
+
+用 [Tcpdump](https://www.tcpdump.org/) 這個工具來稍微理解一下吧,不然光用講的我也聽不懂
+
+執行以下指令開始監聽 `$ sudo tcpdump -i lo port 4000`\
+我這次測試的目標,是在本機上的 4000 port\
+因為是在本機上,所以是 `lo`(loopback) interface(可以用 `$ ifconfig` 查網卡名稱)\
+tcpdump 會監聽目標 port 上所有的流量,所以你就可以用他來觀察連線的狀態
+
+第一個藍色框框表示 TCP 三方交握\
+很明顯符合 `SYN`(S), `SYN + ACK`(S.) 以及 `ACK`(.) 這三種狀態\
+細心的你會發現,三方交握裡面有兩個奇怪的 seq 數字(1708137740 以及 3857014844)\
+sequential number 是一個隨機的數字,方便 server/client 溝通同步用的
+
+你可以看到第一個藍色框框,在第二階段 `SYN + ACK`,它回復的 ack 數字是 1708137740 + 1\
+這很明顯不是巧合,他是根據 client 的 sequential number 再加一回復的(**seq + 1**)\
+不過 server 回復的 sequential number 卻是不同的? 因為 server client 他們會個別產生數字,不會共用
+
+
+
+最後當連線都建立完成之後,你可以看到黃色框框的部份\
+就是在進行資料傳輸了\
+這時你會發現為什麼 sequential number 變成一個 pair 了?\
+而且它似乎擁有某種關聯,`1:377` 然後 `377:14857`\
+聰明的你一定猜到,它是在確保資料的 **到達順序**
+
+
+
+你可能會發現,為什麼會有兩個三方交握(藍色框框)\
+仔細看會發現他是兩個不同的 client 分別跟 4000 port 進行連線\
+我雖然無法確定為什麼會有多個 client 連線,但這證明了一件事情,server 是可以多工處理不同 client 的連線的!\
+而且它還不會亂掉(因為 client port 不同,所以是不同的 [Socket](#socket))
+
+
+
+但藍色框框,最後 server 回 `ACK` 的時候, 為什麼是 1 呢?\
+這是 tcpdump 預設輸出相對 sequence number\
+可以在下指令的時候加一個 flag `-S` 就可以了\
+下圖,`ACK` 回的數字就是 **seq + 1** 了
+
+![](/assets/img/posts/tcpdump2.png)
+
+## Four-way Handshake
+![](/assets/img/posts/tcpdump3.png)
+
+> 再次註明,在原始的 [RFC 793](https://datatracker.ietf.org/doc/html/rfc793) 的定義中\
+> 並沒有指出需要四方握手以結束連線\
+> 我在測試的時候也是有時候有看到,有時候又沒看到
+
+跟三方交握相反,四方握手是用在關閉連線的時候會用到\
+概念在 [Why Handshake is Important](#why-handshake-is-important) 提到\
+基本上是一樣的
+
+這裡的關閉連線是從 server 開始的\
+第一個藍色框框,使用 `FIN + ACK` 來表明我想要中斷連線\
+我想要終止 sequential number 為 `20412` 這段連線\
+並且跟你說,上一段資訊 `1573` 我已經收到了
+
+所以第二段\
+`ACK` client 表示說好的我已經收到了你想要關閉 `20412` 的連線
+
+第三段\
+既然你想要關閉連線,那我這邊也想要關閉 `1573` 的連線(`FIN`)\
+並且 `20412` 連線已經結束了,回一個 `20412 + 1` 的 `ACK` 給你
+
+最後 server 表示,你的 `1573` 關閉請求已經批准!回一個 `1573 + 1` 的 `ACK` 給你
+
+
+
+基本上就是每個人做的每件事情都一定要回\
+所以才會拆成四個步驟來做\
+說到底就是 `server 想關`, `client 想關`, `server 結束`, `client 結束` 這樣
+
+## Congestion Control
+網路是會塞車的,網路頻寬是一個主要的因素\
+相信你有過一個狀況,家裡很多人在用 wifi 的時候,你會感覺到它變慢\
+這個就是網路已經塞車的現象了
+
+說到塞車,假設連假你要出門旅遊\
+從連假的前一天開始就會有塞車的現象\
+這時候你可以選擇當個聰明用路人或者是跟著一起塞\
+一起塞的時候,你會發現到匝道會有管制,幾秒鐘放行幾輛車子這種\
+這就是 **壅塞控制** 的概念
+
+避免過多的車子進入國道,使得塞車的現象變得更嚴重\
+我們可以使用基本的管制措施限制數量,用以緩解塞車的現象
+
+當網路上的封包多到開始掉的時候,一個常見的方法就是減緩發送封包的頻率(`congestion window` :arrow_right: 給定時間內能傳多少資料)\
+對,[TCP](#tcp---transmission-control-protocol) 是會掉封包的,因為底層是 [IP](#ip---internet-protocol) 不可靠傳輸\
+TCP 有自己的偵錯方法,所以我們可以信任它
+
+## telnet
+測試 TCP 連線可以使用 telnet\
+基本的用法就是
+
+```shell
+$ telnet localhost 8080
+```
+
+然後就可以開始傳輸資料了
+
+# UDP - User Datagram Protocol
+UDP 的定義是在 [RFC 768](https://datatracker.ietf.org/doc/html/rfc768)\
+相較於 [TCP](#tcp---transmission-control-protocol),UDP 是不會進行握手的\
+所以他是無連線的 protocol
+
+UDP 相比 [IP](#ip---internet-protocol) 額外新增了兩個服務
+
++ datagram header 中加入錯誤偵測欄位,確保資料無誤
++ process 之間的通訊
+
+UDP 並沒有像 [TCP](#tcp---transmission-control-protocol) 一樣提供可靠性傳輸哦
+
+## UDP Observation
+UDP 在傳送資料前並不會有任何握手確認的動作\
+看一下實際上是不是真的這樣子
+
+> 我們可以用 [Tcpdump](https://www.tcpdump.org/) 以及 [Wireshark](https://www.wireshark.org/download.html) 觀察\
+> 測試指令我們可以用 [netcat](https://netcat.sourceforge.io/) 來測試
+
+![](/assets/img/posts/udpdump.png)
+
+測試 UDP 的指令為 `$ echo "Hello world" | nc -u 127.0.0.1 8083 -w 10`
+
+我們用 netcat(nc) 的指令,發送資料(Hello world) 到本機上的 8083 port\
+`w` flag 是指等待秒數,在這裡我們等 10 秒
+
+你可以看到 tcpdump 的確有抓到我們送過去的資料(沒錯 tcpdump 也可以用來抓 udp traffic)\
+詭異的是它為什麼會顯示長度為 12 呢?
+
+![](/assets/img/posts/udpdump1.png)
+
+透過 wireshark 觀察可以得知,最後一個 byte 是 `0A`\
+參照 [ASCII](https://zh.wikipedia.org/zh-tw/ASCII) 表來對照就是 `LF`\
+所以實際上是 `Hello world\n`, 也就是 12 個 byte 了
+
+
+
+你可以很明顯的看到,UDP 並沒有所謂握手的動作\
+參照 tcpdump 的結果,他是直接傳資料過來的\
+就像有人突然跟你搭話,你有可能沒聽清楚蛤回去\
+封包就掉了
+
+## UDP Transfer Type
+UDP 在傳輸資料的時候有分成三種不同的模式 [Unicast](#unicast), [Multicast](#multicast) 以及 [Broadcast](#broadcast)
+
+### Unicast
+在 [UDP Observation](#udp-observation) 我們看到的例子就是屬於 unicast\
+他是點對點的傳輸,跟 [TCP](#tcp---transmission-control-protocol) 很像\
+只是沒有握手而已
+
+### Multicast
+相較於單點傳播,multicast 為多點傳播\
+但它跟 [Broadcast](#broadcast) 不一樣\
+多點傳播只會把資料傳給訂閱者,而不會把資料傳給其他人\
+有點類似 `Observer Pattern`(可參考 [設計模式 101 - Observer Pattern \| Shawn Hsu](../../design%20pattern/design-pattern-observer))
+
+multicast 需要執行在特定的 ip 地址上\
+這個是因為它可以確保路由的時候更順利,因為只要送到這個地址的資料我就知道他是 multicast\
+這個區段從 `224.0.0.0` 到 `239.255.255.255`
+
+訂閱 multicast server 的人,每當新訊息來的時候,就會收到\
+類似 mailing list\
+而發送訊息的本人,是不會收到自己發送的訊息的
+
+### Broadcast
+廣播就是所有人都可以收到資料了\
+它不需要明確的加入 "群組", 就可以收到資料
+
+同樣的,廣播也需要一個地址 `255.255.255.255`\
+把資料丟過去,所有同個區域網路都會收到你的訊息\
+而這其實會造成一些問題
+
+不是每個人都需要這個訊息\
+它會造成網路壅塞(c.f. [Congestion Control](#congestion-control)),這顯然不好\
+所以其實 broadcast 已經被廢棄了
+
+# SSL - Secure Sockets Layer(TLS)
+一個常見的誤區,至少對我來說\
+是錯誤的認為 TCP/UDP 這些協定會自己幫我們把資料加密\
+這是錯的 是錯的 錯的!
+
+![](/assets/img/posts/udpdump1.png)
+
+至少你可以從我們做的 wireshark 小實驗中得出\
+我們甚至不用 decrypt 就知道我們送的資料是 `Hello world`
+
+我們能在網路上肆意的遊玩,是因為我們的資料都是加密過的\
+得益於 SSL(i.e. TLS) 的幫助
+
+TLS(現在比較常說 TLS) 是一種補強的 protocol\
+定義於 [RFC 5246](https://datatracker.ietf.org/doc/html/rfc5246)\
+其宗旨是為了提供在網路上雙方的隱私以及資料的完整性
+
+> At the lowest level, layered on top of some reliable\
+> transport protocol (e.g., TCP [TCP]), is the TLS Record Protocol.
+
+TLS 需要跑在可靠性的傳輸協定之上,如 [TCP](#tcp---transmission-control-protocol)
+
++ 隱私性是透過 `對稱性加密演算法` 或 `非對稱式加密演算法` 所提供
++ 資料的完整性是透過 `Message Authenticate Codes(MACs)` 所提供
+
+基本上 TLS 是由兩部份組成 [TLS Record Protocol](#tls-record-protocol) 以及 [TLS Handshake Protocol](#tls-handshake-protocol)
+
+## TLS Record Protocol
+record protocol 主要是用於封裝高階 protocol 的資料\
+舉例來說 HTTP(可參考 [重新認識網路 - HTTP1 與他的小夥伴們 \| Shawn Hsu](../../network/networking-http1))
+
+怎麼封裝呢?\
+將 message-based 的資料包裝成一個可管理的封包\
+適當的壓縮資料,加上 `Message Authenticate Codes(MACs)` 來確保資料完整性
+
+> MACs 不能驗證來源合法性(i.e. 不確定是不是本人簽的)\
+> 如果需要驗證 1. 資料完整性 2. 來源合法性,可以考慮使用數位簽章(digital signature)
+
+## TLS Handshake Protocol
+重頭戲來啦,client 跟 server 要建立一個安全的連線了!
+
++ 他們會先核對基本資料(e.g. `protocol version`, `加密演算法` 等等的)
+ + 然後嘗試做 session resumption(簡單的理解是 connection caching, 這樣就不用重新握手,很方便)
++ 驗證彼此的合法性
+ + 交換 certificate 驗證彼此的身份(透過 CA 組織, 比如說免費的 [Let's Encrypt](https://letsencrypt.org/))
++ 產生 master secret, premaster secret,交換 random number(避免 [relay attack](https://en.wikipedia.org/wiki/Replay_attack))
++ secure session 建立成功! 可以開始享受安全的資料傳輸了!
+
+![](https://infocenter.nokia.com/public/7705SAR234R1A/topic/com.nokia.system-mgmt-guide/graphics/sw1394.png)
+> ref: [TLS Handshake](https://infocenter.nokia.com/public/7705SAR234R1A/index.jsp?topic=%2Fcom.nokia.system-mgmt-guide%2Ftls-handshake.html)
+
+# TCP/UDP Comparison
+
+||TCP|UDP|
+|:--:|:--|:--|
+|Reliable|:heavy_check_mark:|:x:|
+|Ordered|:heavy_check_mark:|:x:|
+|Handshake|:heavy_check_mark:|:x:|
+|Connection|:heavy_check_mark:|:x:|
+|Congestion|:heavy_check_mark:|:x:|
+|Packet size|Large|Small|
+|Used Socket|2|1|
+
+# TCP/UDP Golang Example
+> to be continued
+
+# References
++ 電腦網際網路(ISBN: 978-986-463-950-2)
++ [網際網路協議套組](https://zh.wikipedia.org/wiki/TCP/IP%E5%8D%8F%E8%AE%AE%E6%97%8F)
++ [TCP header format](https://jyhshin.pixnet.net/blog/post/31256044)
++ [What is TCP Three-Way HandShake?](https://www.guru99.com/tcp-3-way-handshake.html)
++ [傳輸控制協定](https://zh.wikipedia.org/wiki/%E4%BC%A0%E8%BE%93%E6%8E%A7%E5%88%B6%E5%8D%8F%E8%AE%AE)
++ [Root Servers](https://www.iana.org/domains/root/servers)
++ [Why does TCP socket programming need two sockets(one welcome socket and one connection socket) but UDP only needs one?](https://stackoverflow.com/questions/41389880/why-does-tcp-socket-programming-need-two-socketsone-welcome-socket-and-one-conn)
++ [TCP: can two different sockets share a port?](https://stackoverflow.com/questions/11129212/tcp-can-two-different-sockets-share-a-port)
++ [透過 TCP/IP 進行三向交握的說明](https://learn.microsoft.com/zh-tw/troubleshoot/windows-server/networking/three-way-handshake-via-tcpip)
++ [Three-Way Handshake](https://github.com/steveLauwh/TCP-IP/blob/master/TCP/Three-Way%20Handshake%20And%20Four-Way%20Wavehand.md)
++ [Why is the ACK flag in a tcpdump represented as a period "." instead of an "A"?](https://stackoverflow.com/questions/60443487/why-is-the-ack-flag-in-a-tcpdump-represented-as-a-period-instead-of-an-a)
++ [tcpdump: Learning how to read UDP packets](https://dzone.com/articles/tcpdump-learning-how-read-udp)
++ [串流技術簡介- 什麼是 UDP, TCP, Unicast, Multicast, RTP, RTSP, RTMP?](https://www.datavideo.com/hk/article/51/streaming-terminology)
++ [What IP to use in order to perform a UDP broadcast?](https://stackoverflow.com/questions/72843819/what-ip-to-use-in-order-to-perform-a-udp-broadcast)
++ [TCP擁塞控制](https://zh.wikipedia.org/zh-tw/TCP%E6%8B%A5%E5%A1%9E%E6%8E%A7%E5%88%B6)
++ [How do multiple clients connect simultaneously to one port, say 80, on a server? [duplicate]](https://stackoverflow.com/questions/3329641/how-do-multiple-clients-connect-simultaneously-to-one-port-say-80-on-a-server)
diff --git a/_posts/random/2024-01-18-real-time-communication.md b/_posts/random/2024-01-18-real-time-communication.md
index 3671d9c2713f..f16a5791c9fd 100644
--- a/_posts/random/2024-01-18-real-time-communication.md
+++ b/_posts/random/2024-01-18-real-time-communication.md
@@ -115,42 +115,7 @@ timeout 設定成一分鐘的情況下\
在這一方面可謂完美的解決了 [Polling](#polling) 以及 [Long Polling](#long-polling) 建立連線的巨大成本帶來的 overhead\
看似完美的解決方案,但是它會遇到另一個問題,file descriptor 數量限制
-
-
-> In UNIX, Everything is a File
-
-事情還得要從作業系統說起\
-UNIX 的設計哲學是,Everything is a File\
-每個東西都是檔案,什麼意思?\
-檔案不就是檔案嗎? 那麼網路,印表機這些也算檔案嗎?\
-依照作業系統的邏輯,如果要詳細區分這些東西為各種不同的類別,那麼實作起來將會無比困難\
-因此,就算是印表機這種東西,底層實作也會將它視為是 **檔案**
-
-建立網路連線,它分成大約兩步驟
-1. 建立 socket(i.e. file descriptor),建立好一個對接的端口
-2. 建立連線(並且透過 socket 進行資料的傳輸)
-
-而 socket 就是那個 **檔案**\
-每個應用程式都擁有自己的 socket 接口\
-你可以使用 [lsof](https://linux.die.net/man/8/lsof) 這個指令查看當前 internet file descriptor 的狀況\
-執行 `$ sudo lsof -i` 你會看到類似這張圖的輸出
-![](/assets/img/posts/lsof.png)
-可以很清楚的看到,chrome 瀏覽器開了許多的 socket
-
-> 你應該還會看到其他應用程式,像我的還有 telegram, docker ... etc.
-
-
-
-socket 有沒有數量限制呢? 或者說比較 general 一點\
-file descriptor 有沒有上限?\
-我想答案很明顯是有的
-
-```shell
-$ ulimit -n
-1024
-```
-
-> 可參考 [man ulimit](https://linuxcommand.org/lc3_man_pages/ulimith.html)
+> 有關 socket 的介紹可參考 [重新認識網路 - 從基礎開始 \| Shawn Hsu](../../network/networking-basics#socket)
我的電腦,預設 file descriptor 上限數量為 `1024`\
也就是說一個 process 的 file descriptor 上限就那麼多\
diff --git a/_posts/website/2023-03-08-website-jwt.md b/_posts/website/2023-03-08-website-jwt.md
index d167a761a910..192cc56ccf9d 100644
--- a/_posts/website/2023-03-08-website-jwt.md
+++ b/_posts/website/2023-03-08-website-jwt.md
@@ -312,8 +312,11 @@ client 要驗證的唯一方式 是不是用金鑰下去算算看?\
就代表這個 token 來源被驗證了! 嗎
記不記得在前面 [JWS(JSON Web Signature)](#jwsjson-web-signature) 有提到\
-簽章有兩種方式, digital signature 跟 Message Authentication Codes(MACs)\
-其中 MACs 是沒辦法驗證來源的
+簽章有兩種方式, digital signature 跟 Message Authentication Codes(MACs)
+
+> 數位簽章(digital signature) 可以驗證 1. 資料完整性 2. 來源合法性\
+> Message Authentication Codes(MACs) 可以驗證 1. 資料完整性\
+> 其中 MACs 是沒辦法驗證來源的
道理倒也淺顯易懂\
如果第三方取得你的 signing key, 我是不是也能偽造簽章了?
@@ -386,6 +389,8 @@ signature 的計算是使用存在 server 上的 signing key 加上前面 header
如果真的有傳送機密訊息的需求,使用 [JWE](#jwejson-web-encryption) 是最好的選擇\
不過普遍來說,我們認為 http 的 TLS 已經足夠應付大多數的場景了
+> 有關 TLS 的介紹可以參考 [重新認識網路 - 從基礎開始 \| Shawn Hsu](../../network/networking-basics#ssl---secure-sockets-layertls)
+
既然 JWS 沒有進行加密\
一般來說是不建議在上面塞入任何敏感資訊\
以我自己來說,我通常只會帶個 user id 之類洩漏也不會怎麼樣的資料\
diff --git a/assets/img/posts/tcpdump1.png b/assets/img/posts/tcpdump1.png
new file mode 100644
index 000000000000..67faef941243
Binary files /dev/null and b/assets/img/posts/tcpdump1.png differ
diff --git a/assets/img/posts/tcpdump2.png b/assets/img/posts/tcpdump2.png
new file mode 100644
index 000000000000..35434bd0fba9
Binary files /dev/null and b/assets/img/posts/tcpdump2.png differ
diff --git a/assets/img/posts/tcpdump3.png b/assets/img/posts/tcpdump3.png
new file mode 100644
index 000000000000..8a2df543855b
Binary files /dev/null and b/assets/img/posts/tcpdump3.png differ
diff --git a/assets/img/posts/udpdump.png b/assets/img/posts/udpdump.png
new file mode 100644
index 000000000000..74f1cd3d8d15
Binary files /dev/null and b/assets/img/posts/udpdump.png differ
diff --git a/assets/img/posts/udpdump1.png b/assets/img/posts/udpdump1.png
new file mode 100644
index 000000000000..53e7429dcf2c
Binary files /dev/null and b/assets/img/posts/udpdump1.png differ