summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTing-Wei Lan <lantw44@gmail.com>2014-07-07 16:24:56 +0800
committerTing-Wei Lan <lantw44@gmail.com>2014-07-07 16:26:22 +0800
commit664d22a7becc2a5e83c7038b609aec947c075d79 (patch)
tree32e2079181c1ff878e66017e89a150b98ed1d306
parent46d839d352232cb1bb3766d5aa1ec48a28cfac50 (diff)
downloadfastalg-wiki-664d22a7becc2a5e83c7038b609aec947c075d79.tar.gz
fastalg-wiki-664d22a7becc2a5e83c7038b609aec947c075d79.tar.zst
fastalg-wiki-664d22a7becc2a5e83c7038b609aec947c075d79.zip
加入已經完成一半的 report
-rw-r--r--Report.asciidoc137
-rw-r--r--ReportImages/fastalg-nfqueue-udp-dns-request.dot43
-rw-r--r--ReportImages/fastalg-nfqueue-udp-dns-request.pngbin0 -> 99355 bytes
-rw-r--r--ReportImages/fastalg-nfqueue-udp-dns-request.svg139
-rw-r--r--ReportImages/fastalg-nfqueue-udp-dns-response.dot17
-rw-r--r--ReportImages/fastalg-nfqueue-udp-dns-response.pngbin0 -> 24816 bytes
-rw-r--r--ReportImages/fastalg-nfqueue-udp-dns-response.svg44
-rw-r--r--ReportImages/fastalg-nfqueue-udp-general.pngbin0 -> 125754 bytes
8 files changed, 380 insertions, 0 deletions
diff --git a/Report.asciidoc b/Report.asciidoc
new file mode 100644
index 0000000..c6f020c
--- /dev/null
+++ b/Report.asciidoc
@@ -0,0 +1,137 @@
+== 第 12 組組員
+ - B01902003 林子傑
+ - B01902062 藍挺瑋
+ - B01902090 許伯駒
+ - B01902110 程鼎元
+
+== 摘要
+設計依據應用層 (Application Layer) 傳輸協定與其欄位內容進行網路位置轉換 (NAT) 的程式。
+
+== 實作
+ - Linux user mode 版本 (`raw5.cpp`)
+ * 使用 raw socket
+ - Linux netfilter queue 版本 (`fastalg-nfqueue`)
+ * 使用 kernel 中的 netfilter queue (nfqueue) 功能
+
+== Linux user mode 版本
+ - 目標
+ * 不用系統設定即可使用
+ - 功能
+ * TODO
+
+== Linux netfilter queue 版本
+ - 目標
+ * Linux 的 netfilter 已經包含許多封包轉送功能,我們嘗試利用它,
+ 以期加速我們的開發速度,並更容易與現有系統整合。
+ * 我們的程式運行在 user mode,再藉由 netfilter queue 從 kernel
+ 取得符合規則的封包(通常是特定通訊協定與特定 port 的封包)。
+ * 將程式執行在 user mode 不僅方便測試,也能使用各種現有的函式庫輔助開發。
+ 同時因為不需要修改 kernel,省去了安裝與維護 kernel module 的困難,
+ 使用者較易上手。但由於功能尚未實作完全,我們不太清楚效能是否會因此受影響。
+
+ - 執行需求
+ * Linux 3.10 以上的 Netfilter 模組。
+ ** IPTables 和 NFTables 應該都能使用,但我們只測試了 NFTables。
+ 若要使用 NFTables,則需要 Linux 3.13 以上。
+ 我們使用的版本是 Fedora 20 提供的 Linux 3.14。
+ * libmnl
+ ** 用來和 kernel 透過 netlink socket 溝通。
+ * libnetfilter_queue
+ ** 用來操作 kernel 中的 netfilter queue。其中還包含了許多輔助用的函式,
+ 例如用來管裡封包的 pktbuff,和 IPv4 / IPv6 / TCP / UDP 封包
+ 解析與偵錯用的函式。但因為這些輔助函式的實作有不少錯誤,
+ 所以我們仍自行實作了不少替代用的函式。這些錯誤都已經向 netfilter
+ 開發者回報,希望在下個版本的 libnetfilter_queue 能夠解決。
+ * GLib 2.12 以上
+ ** 提供各種常見資料結構的實作。我們使用的版本是 2.38。
+
+ - 編譯需求
+ * 支援 C99 的 C 編譯器,常見的 GCC 和 Clang 都能符合要求。
+ * pkg-config 或其他相容的實作。
+ * POSIX 相容的 make 和 shell。
+ * 若有修改程式,則需要 autoconf、automake、libtool。
+
+ - 程式架構
+ * 我們將程式拆為主程式和通訊協定解析函式庫兩個部份。主程式 `fastalg-nfqueue`
+ 處理了大部分的工作,在需要得知應用層的資訊時,會呼叫通訊協定解析函式庫
+ `fastalg-protocol` 中的函式。因此如果要加入更多應用層通訊協定的支援時,
+ 我們只需要修改 `fastalg-protocol` 即可,主程式完全不需要修改。
+ 利用這樣的特性,我們以後還可能用此製作 plugin 系統。
+ * `fastalg-nfqueue` 因為要從 Linux kernel 讀取資料,所以高度依賴 Linux
+ 提供的各種功能,無法移植到不同的平臺。相反的, `fastalg-protocol`
+ 是設計來當作不同實作間共用的函式庫,因此編寫時很注重可攜性,
+ 目前只使用了 `malloc` 、 `free` 和一些很基本的字串處理函式。
+ * `falgnfq-main.c`:
+ 主程式的進入點,初始化地區和時區設定,並藉由環境變數得知使用者的
+ debug 參數。
+ * `falgnfq-private.h`:
+ 各種內部使用的 macro 和 inline function,包含
+ compile-time 和 runtime 的 debug 狀態偵測、錯誤訊息回報,
+ 以及儲存封包用的輔助結構。
+ * `falgnfq-config.c`:
+ 讀取使用者設定值的工具,預計會有從 command line
+ 和設定檔讀取兩種方式,目前只實作從 command line 讀取。
+ * `falgnfq-loop.c`:
+ 接收、分析、暫存、傳送封包,並告知 kernel 我們對封包所作的決定。
+ * `falgnfq-dump.c`:
+ 把從 netfilter queue 得到的封包內容印出來,一個一個 bit 印出,以觀察
+ bit-field 的實際排列狀況,來解決 endian 的相關問題。
+ * `falgnfq-tcp.c`:
+ 產生用於回應 TCP client 和 server 的封包,目前尚未實作完成。
+ * `falgnfq-rng.c`:
+ 安全的亂數產生器,目前是直接使用 `/dev/urandom` 。
+ * `falgproto.h`:
+ `fastalg-protocol` 提供的 public API。
+ * `falgproto.c`:
+ `fastalg-protocol` 中 public API 的實作,
+ 並包含指向各個通訊協定實作的函式指標。
+
+ - UDP 實作
+ * UDP 封包轉送示意圖,以下以 DNS 封包的轉送為例。 +
+ image:ReportImages/fastalg-nfqueue-udp-general.png["UDP General",width=640]
+
+ - DNS 轉送應用
+ * 若在 NAT 後方有多台 DNS server 負責解析不同 hostname 的 IP address,
+ 各司其職,解析領域不重疊,則 NAT 主機可將封包拆開來看內容,確認 request
+ 的 hostname 屬於哪台 DNS server 負責的解析領域後,
+ 再將此封包發給有能力解析的 DNS server。
+
+ - DNS 封包實際轉送過程:client DNS request
+ * image:ReportImages/fastalg-nfqueue-udp-dns-request.png["DNS request",
+ width=640,link="ReportImages/fastalg-nfqueue-udp-dns-request.svg"]
+ * 使用者必須事先在 NFTables 裡加入 NAT 的規則,譬如
+ 「當封包的 mark 為 XXX 時,要將其轉發至 YYY server」。
+ * 從 client 來的封包先送到 NAT 主機,進入 NFTables 的轉送判定流程。
+ 在流程中,一個沒有 mark 的封包經過 NFTables 的中
+ `type filter hook prerouting` 的 chain 時 (*#1*),
+ 會被保留至 netfilter queue,準備傳入 user space 給我們的程式分析 (*#2*)。
+ NFTables 是 Linux kernel 的一部分,有防火牆與 NAT 的功能,
+ 在此借用其處理封包的能力,幫助我們接收與轉發封包。
+ * 透過 netfilter queue,複製好的封包內容會被傳送給 user mode 的
+ `fastalg-nfqueue` 這支程式 (*#3*)。複製的封包內容包含 IP header、
+ UDP header、DNS request 等,也就是從 network layer 到 application layer
+ 的所有內容,可以自行 parse 出封包的各種資訊 (*#4*)。
+ * `fastalg-nfqueue` 就是我們設計的程式,可分析 DNS 封包的內容,
+ 協助封包的轉發。這支程式查看 DNS 封包的內容 (*#5*),分析其 request
+ 適合由哪個 server 回應 (*#6*),並給封包一個對應的 mark。
+ * 一個封包有了 mark, `fastalg-nfqueue` 會請這個封包重新跑一次 NFTables
+ 的轉送判定流程 (*#7*)。此時因為封包已經加上了 mark,所以封包不會再進入
+ netfilter queue,而會通過並進入下一條規則,來到 `type nat hook prerouting`
+ 的 chain (*#8*)。
+ * 由於一開始在封包到達前,我們已經在 NFTables 裡加入 NAT 的規則,
+ 封包依據此規則進行 DNAT。特定的 mark,目的地被改成特定的 IP,
+ 封包因而被轉發至持有該 IP 的 server,封包轉送的目標就如願達成 (*#9*)。
+
+ - DNS 封包實際轉送過程:server DNS response
+ * image:ReportImages/fastalg-nfqueue-udp-dns-response.png["DNS response",
+ width=320,link="ReportImages/fastalg-nfqueue-udp-dns-response.svg"]
+ * server 處理完 client 的 DNS request 封包,會將 DNS response
+ 封包送回 NAT 主機 (*#1*)。
+ * 從 server 來的 DNS 封包比較好處理,因為 destination port 通常不會再是 53
+ (DNS的專用port),所以進來的封包不再需要經過我們的程式 `fastalg-nfqueue` 。
+ 若是 destination port 還是 53,則另當別論,必須特殊處理,
+ 不過這種狀況機率極低,正常連線不該會出現。
+ * 如此一來,封包不需經過我們的程式,直接交由 NFTable 處理。其 port
+ 對應的是哪個 client,NFTables 進行 SNAT 時就將此封包的 source IP
+ 轉為 NAT 主機的 IP,封包就能如願轉送回 client 手中 (*#2*)。
+
diff --git a/ReportImages/fastalg-nfqueue-udp-dns-request.dot b/ReportImages/fastalg-nfqueue-udp-dns-request.dot
new file mode 100644
index 0000000..ef5e12a
--- /dev/null
+++ b/ReportImages/fastalg-nfqueue-udp-dns-request.dot
@@ -0,0 +1,43 @@
+digraph G {
+ graph [layout=dot fontname="Cantarell,sans-serif"];
+ node [shape=Mrecord fontname="Cantarell,sans-serif"];
+ edge [fontname="Cantarell,sans-serif"];
+
+ subgraph cluster_kernel {
+ label = <<font point-size="20">Linux (kernel mode)</font>>;
+ color = "brown";
+ nft_filter_prerouting [label="NFTables 規則 (filter, prerouting)"];
+ nfqueue [label="Netfilter user space queue"];
+ nft_nat_prerouting [label="NFTables 規則 (nat, prerouting)"];
+ }
+
+ subgraph cluster_fastalg_nfqueue {
+ label = <<font point-size="20">fastalg-nfqueue (user mode)</font>>;
+ color = "blue";
+ netlink_socket [label="Netlink socket"];
+ udp_inspect [label="UDP 封包分析程式"];
+ }
+
+ subgraph cluster_fastalg_protocol {
+ label = <<font point-size="20">fastalg-protocol (user mode library)</font>>;
+ color = "green3";
+ dns_parser [label="DNS 分析函式"];
+ hostname_matcher [label="Hostname 配對函式"];
+ }
+
+ pkt_in [label="DNS request 封包輸入"];
+ pkt_out [label="DNS request 封包輸出"];
+
+ pkt_in -> nft_filter_prerouting [label=<<font color="red"><b>1</b></font>>];
+ nft_filter_prerouting -> nfqueue [label=<<font color="red"><b>2</b></font> Enqueue>];
+ nfqueue -> netlink_socket [label=<<font color="red"><b>3</b></font> Dequeue>];
+ netlink_socket -> udp_inspect [label=<<font color="blue"><b>4</b></font>>];
+ udp_inspect -> dns_parser [label=<<font color="blue"><b>5</b></font> packet list>];
+ dns_parser -> udp_inspect;
+ udp_inspect -> hostname_matcher [label=<<font color="blue"><b>6</b></font> hostname>];
+ hostname_matcher -> udp_inspect;
+ udp_inspect -> nft_filter_prerouting [label=<<font color="blue"><b>7</b></font> Set packet mark + Verdict>];
+
+ nft_filter_prerouting -> nft_nat_prerouting [label=<<font color="green4"><b>8</b></font>>];
+ nft_nat_prerouting -> pkt_out [label=<<font color="green4"><b>9</b></font>>];
+}
diff --git a/ReportImages/fastalg-nfqueue-udp-dns-request.png b/ReportImages/fastalg-nfqueue-udp-dns-request.png
new file mode 100644
index 0000000..c489516
--- /dev/null
+++ b/ReportImages/fastalg-nfqueue-udp-dns-request.png
Binary files differ
diff --git a/ReportImages/fastalg-nfqueue-udp-dns-request.svg b/ReportImages/fastalg-nfqueue-udp-dns-request.svg
new file mode 100644
index 0000000..81c7572
--- /dev/null
+++ b/ReportImages/fastalg-nfqueue-udp-dns-request.svg
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.34.0 (20140110.0949)
+ -->
+<!-- Title: G Pages: 1 -->
+<svg width="675pt" height="596pt"
+ viewBox="0.00 0.00 675.00 596.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 592)">
+<title>G</title>
+<polygon fill="white" stroke="white" points="-4,4 -4,-592 671,-592 671,4 -4,4"/>
+<g id="clust1" class="cluster"><title>cluster_kernel</title>
+<polygon fill="none" stroke="brown" points="55,-334 55,-508 483,-508 483,-334 55,-334"/>
+<text text-anchor="start" x="180.5" y="-488" font-family="Cantarell,sans-serif" font-size="20.00">Linux (kernel mode)</text>
+</g>
+<g id="clust2" class="cluster"><title>cluster_fastalg_nfqueue</title>
+<polygon fill="none" stroke="blue" points="8,-126 8,-300 279,-300 279,-126 8,-126"/>
+<text text-anchor="start" x="16" y="-280" font-family="Cantarell,sans-serif" font-size="20.00">fastalg&#45;nfqueue (user mode)</text>
+</g>
+<g id="clust3" class="cluster"><title>cluster_fastalg_protocol</title>
+<polygon fill="none" stroke="#00cd00" points="16,-8 16,-92 345,-92 345,-8 16,-8"/>
+<text text-anchor="start" x="24" y="-72" font-family="Cantarell,sans-serif" font-size="20.00">fastalg&#45;protocol (user mode library)</text>
+</g>
+<!-- nft_filter_prerouting -->
+<g id="node1" class="node"><title>nft_filter_prerouting</title>
+<path fill="none" stroke="black" d="M265.5,-433C265.5,-433 462.5,-433 462.5,-433 468.5,-433 474.5,-439 474.5,-445 474.5,-445 474.5,-457 474.5,-457 474.5,-463 468.5,-469 462.5,-469 462.5,-469 265.5,-469 265.5,-469 259.5,-469 253.5,-463 253.5,-457 253.5,-457 253.5,-445 253.5,-445 253.5,-439 259.5,-433 265.5,-433"/>
+<text text-anchor="middle" x="364" y="-447.3" font-family="Cantarell,sans-serif" font-size="14.00">NFTables 規則 (filter, prerouting)</text>
+</g>
+<!-- nfqueue -->
+<g id="node2" class="node"><title>nfqueue</title>
+<path fill="none" stroke="black" d="M75,-343C75,-343 233,-343 233,-343 239,-343 245,-349 245,-355 245,-355 245,-367 245,-367 245,-373 239,-379 233,-379 233,-379 75,-379 75,-379 69,-379 63,-373 63,-367 63,-367 63,-355 63,-355 63,-349 69,-343 75,-343"/>
+<text text-anchor="middle" x="154" y="-357.3" font-family="Cantarell,sans-serif" font-size="14.00">Netfilter user space queue</text>
+</g>
+<!-- nft_filter_prerouting&#45;&gt;nfqueue -->
+<g id="edge2" class="edge"><title>nft_filter_prerouting&#45;&gt;nfqueue</title>
+<path fill="none" stroke="black" d="M323.261,-432.928C289.209,-418.659 240.506,-398.25 204.078,-382.985"/>
+<polygon fill="black" stroke="black" points="205.201,-379.661 194.626,-379.024 202.496,-386.117 205.201,-379.661"/>
+<text text-anchor="start" x="277" y="-403.3" font-family="Cantarell,sans-serif" font-weight="bold" font-size="14.00" fill="red">2</text>
+<text text-anchor="start" x="287" y="-403.3" font-family="Cantarell,sans-serif" font-size="14.00"> Enqueue</text>
+</g>
+<!-- nft_nat_prerouting -->
+<g id="node3" class="node"><title>nft_nat_prerouting</title>
+<path fill="none" stroke="black" d="M275,-343C275,-343 463,-343 463,-343 469,-343 475,-349 475,-355 475,-355 475,-367 475,-367 475,-373 469,-379 463,-379 463,-379 275,-379 275,-379 269,-379 263,-373 263,-367 263,-367 263,-355 263,-355 263,-349 269,-343 275,-343"/>
+<text text-anchor="middle" x="369" y="-357.3" font-family="Cantarell,sans-serif" font-size="14.00">NFTables 規則 (nat, prerouting)</text>
+</g>
+<!-- nft_filter_prerouting&#45;&gt;nft_nat_prerouting -->
+<g id="edge10" class="edge"><title>nft_filter_prerouting&#45;&gt;nft_nat_prerouting</title>
+<path fill="none" stroke="black" d="M364.988,-432.614C365.691,-420.24 366.65,-403.369 367.453,-389.22"/>
+<polygon fill="black" stroke="black" points="370.958,-389.233 368.031,-379.05 363.97,-388.836 370.958,-389.233"/>
+<text text-anchor="start" x="366" y="-403.3" font-family="Cantarell,sans-serif" font-weight="bold" font-size="14.00" fill="#008b00">8</text>
+</g>
+<!-- netlink_socket -->
+<g id="node4" class="node"><title>netlink_socket</title>
+<path fill="none" stroke="black" d="M134.5,-225C134.5,-225 217.5,-225 217.5,-225 223.5,-225 229.5,-231 229.5,-237 229.5,-237 229.5,-249 229.5,-249 229.5,-255 223.5,-261 217.5,-261 217.5,-261 134.5,-261 134.5,-261 128.5,-261 122.5,-255 122.5,-249 122.5,-249 122.5,-237 122.5,-237 122.5,-231 128.5,-225 134.5,-225"/>
+<text text-anchor="middle" x="176" y="-239.3" font-family="Cantarell,sans-serif" font-size="14.00">Netlink socket</text>
+</g>
+<!-- nfqueue&#45;&gt;netlink_socket -->
+<g id="edge3" class="edge"><title>nfqueue&#45;&gt;netlink_socket</title>
+<path fill="none" stroke="black" d="M157.246,-342.884C160.821,-324.036 166.618,-293.469 170.822,-271.304"/>
+<polygon fill="black" stroke="black" points="174.316,-271.663 172.741,-261.186 167.438,-270.359 174.316,-271.663"/>
+<text text-anchor="start" x="164" y="-313.3" font-family="Cantarell,sans-serif" font-weight="bold" font-size="14.00" fill="red">3</text>
+<text text-anchor="start" x="174" y="-313.3" font-family="Cantarell,sans-serif" font-size="14.00"> Dequeue</text>
+</g>
+<!-- pkt_out -->
+<g id="node9" class="node"><title>pkt_out</title>
+<path fill="none" stroke="black" d="M302,-225C302,-225 436,-225 436,-225 442,-225 448,-231 448,-237 448,-237 448,-249 448,-249 448,-255 442,-261 436,-261 436,-261 302,-261 302,-261 296,-261 290,-255 290,-249 290,-249 290,-237 290,-237 290,-231 296,-225 302,-225"/>
+<text text-anchor="middle" x="369" y="-239.3" font-family="Cantarell,sans-serif" font-size="14.00">DNS request 封包輸出</text>
+</g>
+<!-- nft_nat_prerouting&#45;&gt;pkt_out -->
+<g id="edge11" class="edge"><title>nft_nat_prerouting&#45;&gt;pkt_out</title>
+<path fill="none" stroke="black" d="M369,-342.884C369,-324.036 369,-293.469 369,-271.304"/>
+<polygon fill="black" stroke="black" points="372.5,-271.186 369,-261.186 365.5,-271.186 372.5,-271.186"/>
+<text text-anchor="start" x="369" y="-313.3" font-family="Cantarell,sans-serif" font-weight="bold" font-size="14.00" fill="#008b00">9</text>
+</g>
+<!-- udp_inspect -->
+<g id="node5" class="node"><title>udp_inspect</title>
+<path fill="none" stroke="black" d="M122,-135C122,-135 232,-135 232,-135 238,-135 244,-141 244,-147 244,-147 244,-159 244,-159 244,-165 238,-171 232,-171 232,-171 122,-171 122,-171 116,-171 110,-165 110,-159 110,-159 110,-147 110,-147 110,-141 116,-135 122,-135"/>
+<text text-anchor="middle" x="177" y="-149.3" font-family="Cantarell,sans-serif" font-size="14.00">UDP 封包分析程式</text>
+</g>
+<!-- netlink_socket&#45;&gt;udp_inspect -->
+<g id="edge4" class="edge"><title>netlink_socket&#45;&gt;udp_inspect</title>
+<path fill="none" stroke="black" d="M176.198,-224.614C176.338,-212.24 176.53,-195.369 176.691,-181.22"/>
+<polygon fill="black" stroke="black" points="180.192,-181.09 176.806,-171.05 173.193,-181.01 180.192,-181.09"/>
+<text text-anchor="start" x="177" y="-195.3" font-family="Cantarell,sans-serif" font-weight="bold" font-size="14.00" fill="blue">4</text>
+</g>
+<!-- udp_inspect&#45;&gt;nft_filter_prerouting -->
+<g id="edge9" class="edge"><title>udp_inspect&#45;&gt;nft_filter_prerouting</title>
+<path fill="none" stroke="black" d="M244.291,-162.749C317.319,-173.597 427.478,-194.352 457,-224 470.582,-237.641 506.116,-341.495 484,-380 471.33,-402.058 448.732,-417.822 426.537,-428.735"/>
+<polygon fill="black" stroke="black" points="425.008,-425.586 417.413,-432.972 427.957,-431.934 425.008,-425.586"/>
+<text text-anchor="start" x="489" y="-313.3" font-family="Cantarell,sans-serif" font-weight="bold" font-size="14.00" fill="blue">7</text>
+<text text-anchor="start" x="499" y="-313.3" font-family="Cantarell,sans-serif" font-size="14.00"> Set packet mark + Verdict</text>
+</g>
+<!-- dns_parser -->
+<g id="node6" class="node"><title>dns_parser</title>
+<path fill="none" stroke="black" d="M43.5,-17C43.5,-17 126.5,-17 126.5,-17 132.5,-17 138.5,-23 138.5,-29 138.5,-29 138.5,-41 138.5,-41 138.5,-47 132.5,-53 126.5,-53 126.5,-53 43.5,-53 43.5,-53 37.5,-53 31.5,-47 31.5,-41 31.5,-41 31.5,-29 31.5,-29 31.5,-23 37.5,-17 43.5,-17"/>
+<text text-anchor="middle" x="85" y="-31.3" font-family="Cantarell,sans-serif" font-size="14.00">DNS 分析函式</text>
+</g>
+<!-- udp_inspect&#45;&gt;dns_parser -->
+<g id="edge5" class="edge"><title>udp_inspect&#45;&gt;dns_parser</title>
+<path fill="none" stroke="black" d="M109.893,-144.152C93.2513,-138.845 77.2605,-130.154 67,-116 55.7546,-100.487 61.3082,-79.1745 69.1056,-62.4476"/>
+<polygon fill="black" stroke="black" points="72.3954,-63.7026 73.8457,-53.2074 66.1671,-60.5074 72.3954,-63.7026"/>
+<text text-anchor="start" x="67" y="-105.3" font-family="Cantarell,sans-serif" font-weight="bold" font-size="14.00" fill="blue">5</text>
+<text text-anchor="start" x="77" y="-105.3" font-family="Cantarell,sans-serif" font-size="14.00"> packet list</text>
+</g>
+<!-- hostname_matcher -->
+<g id="node7" class="node"><title>hostname_matcher</title>
+<path fill="none" stroke="black" d="M188,-17C188,-17 306,-17 306,-17 312,-17 318,-23 318,-29 318,-29 318,-41 318,-41 318,-47 312,-53 306,-53 306,-53 188,-53 188,-53 182,-53 176,-47 176,-41 176,-41 176,-29 176,-29 176,-23 182,-17 188,-17"/>
+<text text-anchor="middle" x="247" y="-31.3" font-family="Cantarell,sans-serif" font-size="14.00">Hostname 配對函式</text>
+</g>
+<!-- udp_inspect&#45;&gt;hostname_matcher -->
+<g id="edge7" class="edge"><title>udp_inspect&#45;&gt;hostname_matcher</title>
+<path fill="none" stroke="black" d="M181.262,-134.974C184.274,-124.5 188.868,-111.019 195,-100 202.73,-86.108 213.538,-72.2257 223.3,-60.9586"/>
+<polygon fill="black" stroke="black" points="226.125,-63.0488 230.164,-53.2539 220.898,-58.3925 226.125,-63.0488"/>
+<text text-anchor="start" x="195" y="-105.3" font-family="Cantarell,sans-serif" font-weight="bold" font-size="14.00" fill="blue">6</text>
+<text text-anchor="start" x="205" y="-105.3" font-family="Cantarell,sans-serif" font-size="14.00"> hostname</text>
+</g>
+<!-- dns_parser&#45;&gt;udp_inspect -->
+<g id="edge6" class="edge"><title>dns_parser&#45;&gt;udp_inspect</title>
+<path fill="none" stroke="black" d="M103.898,-53.129C116.883,-65.4419 134.048,-82.835 147,-100 153.085,-108.065 158.864,-117.478 163.695,-126.062"/>
+<polygon fill="black" stroke="black" points="160.678,-127.841 168.535,-134.948 166.825,-124.492 160.678,-127.841"/>
+</g>
+<!-- hostname_matcher&#45;&gt;udp_inspect -->
+<g id="edge8" class="edge"><title>hostname_matcher&#45;&gt;udp_inspect</title>
+<path fill="none" stroke="black" d="M260.491,-53.2298C272.156,-70.3808 285.228,-96.841 272,-116 267.102,-123.094 260.612,-128.791 253.315,-133.367"/>
+<polygon fill="black" stroke="black" points="251.514,-130.363 244.427,-138.239 254.878,-136.501 251.514,-130.363"/>
+</g>
+<!-- pkt_in -->
+<g id="node8" class="node"><title>pkt_in</title>
+<path fill="none" stroke="black" d="M297,-551C297,-551 431,-551 431,-551 437,-551 443,-557 443,-563 443,-563 443,-575 443,-575 443,-581 437,-587 431,-587 431,-587 297,-587 297,-587 291,-587 285,-581 285,-575 285,-575 285,-563 285,-563 285,-557 291,-551 297,-551"/>
+<text text-anchor="middle" x="364" y="-565.3" font-family="Cantarell,sans-serif" font-size="14.00">DNS request 封包輸入</text>
+</g>
+<!-- pkt_in&#45;&gt;nft_filter_prerouting -->
+<g id="edge1" class="edge"><title>pkt_in&#45;&gt;nft_filter_prerouting</title>
+<path fill="none" stroke="black" d="M364,-550.884C364,-532.036 364,-501.469 364,-479.304"/>
+<polygon fill="black" stroke="black" points="367.5,-479.186 364,-469.186 360.5,-479.186 367.5,-479.186"/>
+<text text-anchor="start" x="364" y="-521.3" font-family="Cantarell,sans-serif" font-weight="bold" font-size="14.00" fill="red">1</text>
+</g>
+</g>
+</svg>
diff --git a/ReportImages/fastalg-nfqueue-udp-dns-response.dot b/ReportImages/fastalg-nfqueue-udp-dns-response.dot
new file mode 100644
index 0000000..d30ca0f
--- /dev/null
+++ b/ReportImages/fastalg-nfqueue-udp-dns-response.dot
@@ -0,0 +1,17 @@
+digraph G {
+ graph [layout=dot fontname="Cantarell,sans-serif"];
+ node [shape=Mrecord fontname="Cantarell,sans-serif"];
+ edge [fontname="Cantarell,sans-serif"];
+
+ subgraph cluster_kernel {
+ label = <<font point-size="20">Linux (kernel mode)</font>>;
+ color = "brown";
+ nft_nat_postrouting [label="NFTables 規則 (nat, postrouting)"];
+ }
+
+ pkt_in [label="DNS response 封包輸入"];
+ pkt_out [label="DNS response 封包輸出"];
+
+ pkt_in -> nft_nat_postrouting [label=<<font color="red"><b>1</b></font>>];
+ nft_nat_postrouting -> pkt_out [label=<<font color="red"><b>2</b></font>>];
+}
diff --git a/ReportImages/fastalg-nfqueue-udp-dns-response.png b/ReportImages/fastalg-nfqueue-udp-dns-response.png
new file mode 100644
index 0000000..89b910c
--- /dev/null
+++ b/ReportImages/fastalg-nfqueue-udp-dns-response.png
Binary files differ
diff --git a/ReportImages/fastalg-nfqueue-udp-dns-response.svg b/ReportImages/fastalg-nfqueue-udp-dns-response.svg
new file mode 100644
index 0000000..8dd0493
--- /dev/null
+++ b/ReportImages/fastalg-nfqueue-udp-dns-response.svg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.34.0 (20140110.0949)
+ -->
+<!-- Title: G Pages: 1 -->
+<svg width="260pt" height="254pt"
+ viewBox="0.00 0.00 260.00 254.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 250)">
+<title>G</title>
+<polygon fill="white" stroke="white" points="-4,4 -4,-250 256,-250 256,4 -4,4"/>
+<g id="clust1" class="cluster"><title>cluster_kernel</title>
+<polygon fill="none" stroke="brown" points="8,-82 8,-166 244,-166 244,-82 8,-82"/>
+<text text-anchor="start" x="37.5" y="-146" font-family="Cantarell,sans-serif" font-size="20.00">Linux (kernel mode)</text>
+</g>
+<!-- nft_nat_postrouting -->
+<g id="node1" class="node"><title>nft_nat_postrouting</title>
+<path fill="none" stroke="black" d="M28.5,-91C28.5,-91 223.5,-91 223.5,-91 229.5,-91 235.5,-97 235.5,-103 235.5,-103 235.5,-115 235.5,-115 235.5,-121 229.5,-127 223.5,-127 223.5,-127 28.5,-127 28.5,-127 22.5,-127 16.5,-121 16.5,-115 16.5,-115 16.5,-103 16.5,-103 16.5,-97 22.5,-91 28.5,-91"/>
+<text text-anchor="middle" x="126" y="-105.3" font-family="Cantarell,sans-serif" font-size="14.00">NFTables 規則 (nat, postrouting)</text>
+</g>
+<!-- pkt_out -->
+<g id="node3" class="node"><title>pkt_out</title>
+<path fill="none" stroke="black" d="M54,-1C54,-1 198,-1 198,-1 204,-1 210,-7 210,-13 210,-13 210,-25 210,-25 210,-31 204,-37 198,-37 198,-37 54,-37 54,-37 48,-37 42,-31 42,-25 42,-25 42,-13 42,-13 42,-7 48,-1 54,-1"/>
+<text text-anchor="middle" x="126" y="-15.3" font-family="Cantarell,sans-serif" font-size="14.00">DNS response 封包輸出</text>
+</g>
+<!-- nft_nat_postrouting&#45;&gt;pkt_out -->
+<g id="edge2" class="edge"><title>nft_nat_postrouting&#45;&gt;pkt_out</title>
+<path fill="none" stroke="black" d="M126,-90.614C126,-78.2403 126,-61.3686 126,-47.2198"/>
+<polygon fill="black" stroke="black" points="129.5,-47.0504 126,-37.0504 122.5,-47.0504 129.5,-47.0504"/>
+<text text-anchor="start" x="126" y="-61.3" font-family="Cantarell,sans-serif" font-weight="bold" font-size="14.00" fill="red">2</text>
+</g>
+<!-- pkt_in -->
+<g id="node2" class="node"><title>pkt_in</title>
+<path fill="none" stroke="black" d="M54,-209C54,-209 198,-209 198,-209 204,-209 210,-215 210,-221 210,-221 210,-233 210,-233 210,-239 204,-245 198,-245 198,-245 54,-245 54,-245 48,-245 42,-239 42,-233 42,-233 42,-221 42,-221 42,-215 48,-209 54,-209"/>
+<text text-anchor="middle" x="126" y="-223.3" font-family="Cantarell,sans-serif" font-size="14.00">DNS response 封包輸入</text>
+</g>
+<!-- pkt_in&#45;&gt;nft_nat_postrouting -->
+<g id="edge1" class="edge"><title>pkt_in&#45;&gt;nft_nat_postrouting</title>
+<path fill="none" stroke="black" d="M126,-208.884C126,-190.036 126,-159.469 126,-137.304"/>
+<polygon fill="black" stroke="black" points="129.5,-137.186 126,-127.186 122.5,-137.186 129.5,-137.186"/>
+<text text-anchor="start" x="126" y="-179.3" font-family="Cantarell,sans-serif" font-weight="bold" font-size="14.00" fill="red">1</text>
+</g>
+</g>
+</svg>
diff --git a/ReportImages/fastalg-nfqueue-udp-general.png b/ReportImages/fastalg-nfqueue-udp-general.png
new file mode 100644
index 0000000..125ebb8
--- /dev/null
+++ b/ReportImages/fastalg-nfqueue-udp-general.png
Binary files differ