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 應用 Builder,專注於大型平台架構與簡化複雜系統設計,從電商系統到訂閱與收費平台,結合 AI Agent、AI 整合與自動化開發,打造高效率且可持續演進的產品技術基礎。閱讀更多

覺得這篇有幫助?

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

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

留言

訂閱電子報

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

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

熱門文章

View all
Mark Ku
··603

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

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

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

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

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

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

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

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

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

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

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

訓練自己的 AI 語音:硬體門檻、開源模型比較與 LoRA 微調
Net core 應用程式,透過 Frpc 內網穿透時,取得用戶端真實 IP - Mark Ku's Blog