== 第 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*)。