Mark Ku's Blog

問題

大型網站架構,通常會使用負載平衡或反向代理,通常都是 透過 X-Forwarded-For 取得用戶端 Ip,但因為 Frpc 的 https模式只能透過 proxy tocol 協定才能取得真實 IP,但是微軟的網頁伺服器,內建不支援這個協定,因此需要透過 nginx 轉發才能獲得真實用戶端的 IP。

何謂 Proxy protocol

當 Proxy Protocol 功能啟用後,frpc 在和本地服務建立連接後,會先發送一段 Proxy Protocol 的協議內容給本地服務,本地服務通過解析這一內容可以獲得訪問用戶的真實 IP。所以不僅僅是 HTTP 服務,任何的 TCP 服務,只要支持這一協議,都可以獲得用戶的真實 IP 地址。

傳統代理伺服器和應用程式間的 IP傳遞是透過,Header 中的 X-Forwarded-For 所取得的 IP,是有機會被竄改的,但 proxy protocoL,實作原理是透過網路底層 tcpip 交握時取得,因此能避免被篡改被篡改,也比較安全

Frpc 取得 IP 的方式種類

Fpc 取得 ip 的方式

  1. http(非加密協定) - 可以從 X-Forwarded-For 取得用戶端真實 ip
  2. 如果是您要採用 https 則,一定得透過 proxy protocol 底層協定取得用戶端 Ip.

首先編輯你的 frpc.ini 的設定,將 proxy_protocol_version 改成 v2

[common]
server_addr = your public frps url 
server_port = 7000
auth_token = you token
pool_count = 10000
proxy_protocol_version = v2

[web]
type = https
local_port = 443
custom_domains = www.markkulab.net
proxy_protocol_version = v2

接著 nginx.config 的設定

upstream frp {
	server 34.80.106.95:80;  # 这个是frp_server的内网ip和http监听端口
}

server {
    listen 80;
    server_name www.letgo.com.tw;
    server_tokens off;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server
	{
	listen 80 proxy_protocol;
	listen 443 ssl http2 proxy_protocol;
	listen [::]:443 ssl http2;
	server_name www.letgo.com.tw; # local server ip

	set_real_ip_from 172.31.0.1; # frp client ip
	real_ip_recursive on;
	real_ip_header  proxy_protocol;


	    ssl_certificate     /etc/letsencrypt/live/www.letgo.com.tw/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.letgo.com.tw/privkey.pem;
	
	ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;

	ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
	ssl_prefer_server_ciphers on;
	ssl_session_cache shared:SSL:10m;
	ssl_session_timeout 10m;
	add_header Strict-Transport-Security "max-age=31536000";
	error_page 497  https://$host$request_uri;

	location / {
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_protocol_addr;		
		proxy_set_header X-Forwarded-Proto $scheme;
		proxy_pass http://192.168.50.52:8890/; # your local application ip
	}
}

最後,你可以透過請求中的 X-Forwarded-For Header 取得用戶端 IP

public static string GetUserIp(this HttpContext context)
{
    var ip = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();

    if (!string.IsNullOrWhiteSpace(ip))
    {
    ip = ip.Replace("::ffff:", "");
    }           
          
    return ip;
}

參考資料

參考資料1

作者

Mark Ku

10 年以上的軟體工程師,做過北美電商與 AI SaaS 訂閱收費系統。閱讀更多

覺得這篇有幫助?

作者做的免費工具、每日 Podcast 與電子報,都在這裡。

Mark Ku · 本文採用 CC BY 4.0 授權,轉載請註明作者並附上原文連結。

留言

訂閱電子報

訂閱後即時收到新文章通知,不錯過任何技術分享。

提交即表示同意接收電子報,隨時可。

站長的公司

Vibe Coding 架構規劃與陪跑

團隊已經用 AI 做出小工具,卻怕壞了沒人修、需求一變就不敢改?226 Network 幫你把程式放進 Git、密碼另外保管、排程搬上固定主機,再補上交接文件與測試。

熱門文章

View all
Mark Ku
··631

Oracle Cloud 永久免費方案 Linux 主機及固定 IP :0 元打造雲端解決方案

Oracle Cloud 永久免費方案 Linux 主機及固定 IP :0 元打造雲端解決方案
Mark Ku
··471

告別 Postman 收費陷阱!開源 Git 原生 API 測試神器 Bruno 實戰指南

告別 Postman 收費陷阱!開源 Git 原生 API 測試神器 Bruno 實戰指南
Mark Ku
··265

一款免費開源類似於 Notion 類知識庫系統 — Outline Wiki 佈署與備份全攻略

一款免費開源類似於 Notion 類知識庫系統 — Outline Wiki 佈署與備份全攻略
Mark Ku
··216

打造高效 API 管理平台:從 0 開始部署 Kong Gateway - Part 1

打造高效 API 管理平台:從 0 開始部署 Kong Gateway - Part 1
Mark Ku
··208

在 Ubuntu 上設置 Samba 來共享資料夾,讓 Windows 11 用戶可以存取

在 Ubuntu 上設置 Samba 來共享資料夾,讓 Windows 11 用戶可以存取
Mark Ku
··207

訓練自己的 AI 語音:硬體門檻、開源模型比較與 LoRA 微調

訓練自己的 AI 語音:硬體門檻、開源模型比較與 LoRA 微調