Skip to main content
Mark Ku's Blog

The Problem

Large-scale web architectures typically use a load balancer or reverse proxy, and the client IP is usually obtained via the X-Forwarded-For header. However, frpc's HTTPS mode can only expose the real client IP through the Proxy Protocol — and Microsoft's web server (Kestrel) does not natively support that protocol. You therefore need Nginx as a middle layer to extract the real client IP.

What Is Proxy Protocol?

When Proxy Protocol is enabled, frpc sends a Proxy Protocol header to the local service immediately after establishing a connection. The local service parses this header to obtain the visitor's real IP. This works for any TCP service that supports the protocol — not just HTTP.

Traditional reverse proxies pass the client IP via the X-Forwarded-For HTTP header, which can be spoofed by a malicious client. Proxy Protocol, on the other hand, captures the IP at the TCP/IP handshake level, making it tamper-resistant and more secure.

Ways frpc Can Obtain the Client IP

  1. HTTP (unencrypted) — the real client IP can be read from X-Forwarded-For.
  2. HTTPS — you must use the Proxy Protocol at the transport layer to obtain the real client IP.

Step 1: Edit frpc.ini and Set proxy_protocol_version to 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

Step 2: Configure nginx.conf

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
	}
}

Step 3: Read the Client IP from the X-Forwarded-For Header in Your App

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;
}

References

Reference 1

Author

Mark Ku

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

Found this useful?

The author's free tools, daily podcasts and newsletter are all here.

Mark Ku · This article is licensed under CC BY 4.0. Credit the author and link back to the original when reusing it.

Comments

Subscribe to Newsletter

Subscribe to get new posts delivered instantly — never miss a tech share.

By submitting, you agree to receive emails. You can anytime.

Popular Posts

View all
Mark Ku
··636

Oracle Cloud Always Free Tier: Linux Host and Static IP for a $0 Cloud Solution

Oracle Cloud Always Free Tier: Linux Host and Static IP for a $0 Cloud Solution
Mark Ku
··464

Say Goodbye to Postman's Fee Trap! A Hands-on Guide to Bruno, the Open-Source Git-Native API Testing Powerhouse.

Say Goodbye to Postman's Fee Trap! A Hands-on Guide to Bruno, the Open-Source Git-Native API Testing Powerhouse.
Mark Ku
··274

A Free, Open-Source, Notion-like Knowledge Base — A Complete Guide to Deploying and Backing Up Outline Wiki

A Free, Open-Source, Notion-like Knowledge Base — A Complete Guide to Deploying and Backing Up Outline Wiki
Mark Ku
··215

Building an Efficient API Management Platform: Deploying Kong Gateway from Scratch - Part 1

Building an Efficient API Management Platform: Deploying Kong Gateway from Scratch - Part 1
Mark Ku
··206

Training Your Own AI Voice: Hardware Requirements, Open-Source Model Comparison, and LoRA Fine-Tuning

Training Your Own AI Voice: Hardware Requirements, Open-Source Model Comparison, and LoRA Fine-Tuning
Mark Ku
··205

Setting Up Samba on Ubuntu to Share Folders with Windows 11

Setting Up Samba on Ubuntu to Share Folders with Windows 11