summaryrefslogtreecommitdiffstats
path: root/Report.asciidoc
blob: 920ed0e6a41f24e42578d47db971cb94743b8432 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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*)。