Linux 端口轉發 (Port Forwarding/Mapping) 常見於內網服務暴露、多服務共用公網 IP、開發測試環境代理等場景。rinetd 是一款極輕量 (約 50KB)、單執行緒、基於 TCP 的端口轉發工具,配置極簡單、效能極高、支援存取控制與日誌。本文涵蓋原始碼編譯安裝、配置詳解、systemd 服務化、iptables 原生替代方案、Docker 容器化部署與效能調優。
| 工具 | 類型 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|---|
| rinetd | 用戶態 TCP 轉發 | 極輕量、配置簡單、單執行緒無鎖競爭、支援 ACL/日誌 | 僅 TCP、無 UDP、無加密、單執行緒高併發有上限 | 簡單 TCP 端口映射、開發測試、輕量代理 |
| iptables DNAT/SNAT | 核心態 Netfilter | 效能最高、支援 TCP/UDP、無用戶態切換、系統內建 | 配置複雜、需 root、規則持久化麻煩、除錯困難 | 生產環境高效能轉發、防火牆整合 |
| socat | 多功能網路工具 | 支援 TCP/UDP/Unix Socket/SSL/Proxy、極靈活 | 語法複雜、資源佔用較大 | 複雜協定轉換、SSL 終結、Socket 代理 |
| nginx stream | 反向代理 (Layer 4) | 支援負載均衡、健康檢查、SSL、多核心 | 配置相對複雜、記憶體佔用較大 | 生產級 TCP/UDP 負載均衡、SSL 卸載 |
| ssh -L/-R/-D | SSH 隧道 | 加密、認證、無需額外部署、臨時性強 | 單連接、效能較低、不適合長期服務 | 開發臨時隧道、跳板機存取內網 |
# CentOS/RHEL (EPEL)
yum -y install epel-release
yum -y install rinetd
# Debian/Ubuntu
apt -y update && apt -y install rinetd
# Fedora
dnf -y install rinetd
# 安裝編譯工具鏈
yum -y install gcc make glibc-devel
# 下載編譯
wget https://www.boutell.com/rinetd/http/rinetd.tar.gz
tar zxvf rinetd.tar.gz
cd rinetd
make
# 編譯產出 rinetd 二進位檔
cp rinetd /usr/local/sbin/
mkdir -p /etc/rinetd
# 格式: bindaddress bindport connectaddress connectport
# 0.0.0.0 表示監聽所有介面
# 範例: 將本機 8080 轉發到內網 Web 伺服器 80
0.0.0.0 8080 192.168.1.100 80
# 範例: 多對多映射 (原文範例)
1.1.1.1 11 2.2.2.1 3389 # 公網 IP:11 → 內網 RDP
1.1.1.1 12 2.2.2.2 3389 # 公網 IP:12 → 另一台 RDP
1.1.1.1 13 2.2.2.3 22 # 公網 IP:13 → SSH
1.1.1.1 14 2.2.2.4 80 # 公網 IP:14 → HTTP
# 存取控制 (allow/deny 順序生效,預設允許所有)
allow 192.168.1.0/24 # 僅允許內網存取
# allow *.*.*.* # 允許所有 (預設)
# 日誌設定
logfile /var/log/rinetd.log
# logcommon # 通用日誌格式 (可選)
# /etc/systemd/system/rinetd.service
[Unit]
Description=rinetd TCP Port Redirector
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/sbin/rinetd -c /etc/rinetd.conf -f
# -f: 前景執行 (systemd 需要)
# -c: 指定配置檔
Restart=on-failure
RestartSec=5
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=rinetd
# 安全強化
User=nobody
Group=nobody
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ReadWritePaths=/var/log/rinetd.log
[Install]
WantedBy=multi-user.target
# 啟用服務
systemctl daemon-reload
systemctl enable --now rinetd
systemctl status rinetd
journalctl -u rinetd -f # 查看日誌
# 啟動
rinetd -c /etc/rinetd.conf
# 停止
pkill rinetd
# 或
killall rinetd
# 檢查監聽端口
netstat -antup | grep rinetd
ss -antlp | grep rinetd
# 查看日誌
tail -f /var/log/rinetd.log
echo "rinetd -c /etc/rinetd.conf" >> /etc/rc.local
chmod +x /etc/rc.local
# 注意: 現代 systemd 系統建議用上述服務單元
# 變數定義
WAN_IP="202.106.0.20" # 公網 IP
LAN_WEB="192.168.1.88" # 內網 Web 伺服器
# 1. DNAT: 入站流量 公網:2533 → 內網:80
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 2533 -j DNAT --to-destination $LAN_WEB:80
# 2. SNAT: 回程流量 內網:80 → 公網:2533 (確保回應封包源 IP 正確)
iptables -t nat -A POSTROUTING -o eth0 -s $LAN_WEB -p tcp --sport 80 -j SNAT --to-source $WAN_IP:2533
# 3. 若轉發目標非本機,需開啟核心轉發
echo 1 > /proc/sys/net/ipv4/ip_forward
# 永久生效: echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf && sysctl -p
# 4. 允許 FORWARD 鏈通過 (若預設 DROP)
iptables -A FORWARD -i eth0 -o eth1 -p tcp --dport 80 -d $LAN_WEB -j ACCEPT
iptables -A FORWARD -i eth1 -o eth0 -p tcp --sport 80 -s $LAN_WEB -j ACCEPT
# 5. 持久化 (CentOS/RHEL)
service iptables save
# 或 Debian/Ubuntu
iptables-save > /etc/iptables/rules.v4
iptables 關鍵點解析:
PREROUTING DNAT:在路由決策前修改目標 IP:Port,將流量導向內網。POSTROUTING SNAT:在封包送出介面前修改來源 IP:Port,確保內網伺服器回應能正確路由回客戶端 (否則客戶端收到來源 IP 是內網 IP 會丟棄)。ip_forward=1:核心層面啟用 IP 轉發功能,否則封包不會在介面間轉發。FORWARD 鏈:控制是否允許封包通過本機轉發。# Dockerfile
FROM alpine:3.18
RUN apk add --no-cache rinetd
COPY rinetd.conf /etc/rinetd.conf
EXPOSE 11 12 13 14
ENTRYPOINT ["rinetd", "-c", "/etc/rinetd.conf", "-f"]
# 建構映像
docker build -t my-rinetd .
# 執行 (宿主機網路模式效能最佳)
docker run -d --name rinetd \
--network host \
--restart unless-stopped \
-v /etc/rinetd.conf:/etc/rinetd.conf:ro \
my-rinetd
| 參數 | 預設/限制 | 調優建議 |
|---|---|---|
| 單執行緒 | 單核心處理所有連線 | 單實例 ~10k-20k 並發連線;高併發啟動多實例綁定不同 CPU (taskset) 或改用 iptables/nginx |
| TCP 緩衝區 | 系統預設 | 大流量調大 /proc/sys/net/core/rmem_max wmem_max |
| 檔案描述符 | ulimit -n 1024 | ulimit -n 65535 或 systemd LimitNOFILE=65535 |
| 日誌 I/O | 同步寫入 | 高流量關閉日誌或用 logcommon 簡潔格式,改用 syslog 非同步 |
| UDP 支援 | 不支援 | 需 UDP 用 socat/iptables/nginx stream |
allow/deny 規則順序、防火牆 (iptables/firewalld) 是否放行監聽端口、目標服務是否啟動。systemctl restart rinetd 或 pkill -HUP rinetd 不支援熱載入)。rinetd (配置最簡單、資源最輕)。iptables DNAT/SNAT (核心態、效能最強)。nginx stream 或 HAProxy。ssh -L/-R (加密、免部署)。理解各種端口轉發工具的定位與權衡,能讓你在從「開發機快速映射」到「生產集群流量治理」的完整光譜中,精準選擇最適合的方案,避免過度工程或效能瓶頸。