使用 Raspberry Pi 4 Model B 做反向代理伺服器
目標是要使用硬體 Raspberry Pi 4 Model B - 8G 來做反向代理伺服器,並且服務需要可以轉發 TCP 與 UDP。此方案適用於少人數的反向代理伺服器,且成本較低。
初始化
由於是反向代理伺服器,所以需要 IP 固定。硬體為 Raspberry Pi 4 Model B,安裝了 OS ubuntu 22.04,設定方式如下。
1apt -y update && apt upgrade # 主機套件更新
2ip a # 確認網路卡為 eth0
3vim /etc/netplan/50-cloud-init.yaml
1network:
2 ethernets:
3 eth0:
4 dhcp4: no
5 addresses:
6 - 192.168.1.100/24 # Set your desired static IP address and subnet mask
7 routes:
8 - to: 0.0.0.0/0 # Define the default route
9 via: 192.168.1.1 # Set your gateway/router IP address
10 optional: true
11 version: 2
1netplan apply # 重新啟動服務
issue
發現一個現象,當 DHCP 和靜態 IP 同時存在時的網路行為問題。
透過設定 IP address,可以發送非本地的 IP。當設定 dhcp4: yes 且配置了 addresses 時,會是 dhcp 還是 static IP?測試下來機器的 IP 會是 dhcp 所配的 IP;發出去的封包會是以 addresses 所設定,且這現象無法跨網段.
從上面的範例為案例,紀錄測試的結果,如下:
- dhcp 使用的網段是 192.168.1.0/24 被分配到的 IP 是 192.168.1.195,addresses 設定的是 192.168.1.100 的話,發出去的封包來源 IP 會是 192.168.1.100.
- dhcp 使用的網段是 192.168.1.0/24 被分配到的 IP 是 192.168.1.195,addresses 設定的是 192.168.2.100 的話,發出去的封包來源 IP 會是 192.168.1.195.
分析
同時啟用 DHCP 和靜態 IP 時,系統獲取 DHCP 的 IP 但發送封包的來源 IP 選擇取決於目的地與靜態 IP 的網段關係,是符合 Linux 核心處理多 IP 介面和來源 IP 選擇規則的可能行為。
- 一個介面可以有多個 IP: Linux 允許一個網路介面綁定多個 IP 位址,即使它們屬於不同的子網路。
- DHCP 的作用: 當
dhcp4: yes
時,DHCP 客戶端會向伺服器請求 IP 位址、子網路遮罩、預設閘道、DNS 伺服器等資訊,並將這些設定應用到介面上。通常,DHCP 分配的 IP 會被視為該介面的主要 IP。 - 靜態
addresses
的作用: 當同時設定addresses
時,這些 IP 位址會被添加到該介面上,成為介面的次要 IP。 - 來源 IP 的選擇 (Source Address Selection): 當系統要發送一個網路封包時,如果介面有多個 IP,Linux 核心會根據一套規則來決定使用哪個 IP 作為封包的來源 IP。這些規則考慮了:
- 目的地 IP: 如果目的地 IP 在介面某個 IP 的子網路內,系統會傾向於使用該子網路的 IP 作為來源。
- 路由表: 封包會根據路由表決定從哪個介面發出,來源 IP 通常會選自該出站介面上的 IP。
- IP 範圍和作用域 (Scope): 例如,本地環回地址不會用於外部通訊。
- 偏好設定或策略路由 (Policy Routing): 雖然在這個簡單的
netplan
設定中可能不明顯,但在複雜的設定中可以更精確地控制來源 IP。
反向代理伺服器
Nginx
結果: 成功代理,upstream 收到的都是 reverse proxy 的 IP
官方演示 # TCP and UDP Load Balancing
1apt install nginx
2cd /etc/nginx
3cp -rf nginx.conf nginx.conf.origin
4cat >> sites-available/default << EOF
5stream {
6 upstream backend {
7# hash $remote_addr consistent;
8 server 192.168.1.133:80 weight=5;
9 }
10
11 upstream dns {
12# hash $remote_addr consistent;
13 server 192.168.1.133:53;
14 }
15
16 server {
17 listen 80;
18 proxy_pass backend;
19 }
20
21 server {
22 listen 53 udp reuseport;
23 proxy_pass dns;
24 }
25}
26EOF
HAProxy
結果: 失敗代理,不支援 UDP.
1apt install haproxy
2vim /etc/haproxy/haproxy.cfg
1frontend external_tcp
2 bind *:80
3 mode tcp
4 default_backend internal_tcp
5
6backend internal_tcp
7 mode tcp
8 server webserver1 192.168.1.133:80
1service haproxy restart