You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu+CloudFlare+Nginx环境下Node.js应用客户端IP偶尔为空的问题排查求助

Hey there, let's break this down step by step—your issue makes total sense given your stack migration, and those "abnormal" requests you're seeing are actually the root cause of your missing IPs. Let's start with explaining those requests, then fix the problem.

First: What Are Those Weird Requests?

Those requests without Cloudflare headers are direct connections to your VPS IP, not going through Cloudflare at all:

  • The CensysInspect and Expanse user agents come from automated network scanning services—they crawl public IPs to map network perimeters. Since they hit your VPS directly, Cloudflare never touches the request, so headers like cf-connecting-ip don't exist.
  • The xdebug_session_start=phpstorm request is likely either a leftover from local debugging, a misconfigured tool, or even a probe. Again, if it's a direct request to your VPS, no Cloudflare headers are present.

This explains why 3 out of 10 requests return undefined: those are direct bypasses of Cloudflare, not going through its proxy.

Fixing the Missing IP Issue

We'll tackle this in two parts: locking down your VPS to only accept Cloudflare traffic, and improving your Node.js IP logic to handle edge cases.

1. Lock Nginx to Only Accept Cloudflare Traffic

Right now, your Nginx has Cloudflare IPs set for real_ip_from, but it still allows direct connections. Let's add a block to reject non-Cloudflare traffic (or redirect it through Cloudflare):

Add this at the top of your site's Nginx config (before the existing server blocks) to block any requests not coming from Cloudflare IPs:

# Block all non-Cloudflare traffic
geo $allow_cloudflare {
    default 0;
    103.21.244.0/22 1;
    103.22.200.0/22 1;
    103.31.4.0/22 1;
    104.16.0.0/13 1;
    104.24.0.0/14 1;
    108.162.192.0/18 1;
    131.0.72.0/22 1;
    141.101.64.0/18 1;
    162.158.0.0/15 1;
    172.64.0.0/13 1;
    173.245.48.0/20 1;
    188.114.96.0/20 1;
    190.93.240.0/20 1;
    197.234.240.0/22 1;
    198.41.128.0/17 1;
    2400:cb00::/32 1;
    2606:4700::/32 1;
    2803:f800::/32 1;
    2405:b500::/32 1;
    2405:8100::/32 1;
    2a06:98c0::/29 1;
    2c0f:f248::/32 1;
}

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;

    # Reject non-Cloudflare traffic
    if ($allow_cloudflare = 0) {
        return 403;
    }

    # Optional: Redirect to your domain if someone hits the IP directly
    # return 301 https://example.com$request_uri;

    # SSL certs (copy from your existing 443 server block if using the redirect option)
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
}

Then, update your existing server blocks to remove the default_server directive (since we added it to the block above).

This ensures all traffic must go through Cloudflare, so every valid request will have the cf-connecting-ip header.

2. Improve Your Node.js IP Fetching Logic

Even with Cloudflare locked down, it's good to add fallbacks for edge cases. Modify your code to:

  • Check Cloudflare's official headers first
  • Fall back to Nginx-forwarded headers if needed
  • Handle empty values gracefully
const getClientIp = (req) => {
    // Cloudflare's official headers first
    const cfIp = req.header('cf-connecting-ip');
    if (cfIp) return cfIp;

    // Fallback to Nginx-forwarded real IP
    const realIp = req.header('x-real-ip');
    if (realIp) return realIp;

    // Fallback to X-Forwarded-For (split if multiple IPs exist)
    const forwardedFor = req.header('x-forwarded-for');
    if (forwardedFor) {
        // Take the first IP in the list (client IP before proxies)
        return forwardedFor.split(',')[0].trim();
    }

    // Final fallback: direct connection IP (only if all else fails)
    return req.connection.remoteAddress || req.socket.remoteAddress || 'unknown';
};

const clientIp = getClientIp(req);

3. Verify Your Nginx Real IP Configuration

Double-check that your real_ip_header is correctly set in your main site server block:

# Make sure this is present in your main server block
set_real_ip_from 103.21.244.0/22;
# ... all other Cloudflare IP ranges ...
real_ip_header CF-Connecting-IP;

This tells Nginx to replace $remote_addr with the client's real IP from Cloudflare's header, which is useful for logging and other Nginx-level logic.

Final Steps to Test

  1. Reload Nginx to apply changes: sudo systemctl reload nginx
  2. Check your Node.js logs to confirm no more undefined IPs
  3. Try accessing your VPS IP directly (you should get a 403 or redirect)

That should resolve the occasional missing IP issue, and block those unwanted direct scans.

内容的提问来源于stack exchange,提问作者s.khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 13:44:05