使用 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 所設定,且這現象無法跨網段.

從上面的範例為案例,紀錄測試的結果,如下:

  1. dhcp 使用的網段是 192.168.1.0/24 被分配到的 IP 是 192.168.1.195,addresses 設定的是 192.168.1.100 的話,發出去的封包來源 IP 會是 192.168.1.100.
  2. 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 選擇規則的可能行為

  1. 一個介面可以有多個 IP: Linux 允許一個網路介面綁定多個 IP 位址,即使它們屬於不同的子網路。
  2. DHCP 的作用: 當 dhcp4: yes 時,DHCP 客戶端會向伺服器請求 IP 位址、子網路遮罩、預設閘道、DNS 伺服器等資訊,並將這些設定應用到介面上。通常,DHCP 分配的 IP 會被視為該介面的主要 IP。
  3. 靜態 addresses 的作用: 當同時設定 addresses 時,這些 IP 位址會被添加到該介面上,成為介面的次要 IP。
  4. 來源 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
comments powered by Disqus