Mobile wallpaper
1531 字
8 分钟

Nginx Proxy Manager获取客户端真实IP(统一解决办法)

2025-10-28
浏览量 加载中...
本文主要内容

本文介绍如何在Nginx Proxy Manager中获取客户端的真实IP地址,适用于各种后端服务。配置成功后,仅需添加一行代码即可实现真实IP的传递。无需大改所有的反代配置。

以前基本没用过Cloudflare的CDN,cf对我来说,更多的就是DNS解析服务而已,所以一直以来在Nginx Proxy Manager(以下简称NPM)中配置反代时,其默认的$remote_addr配置就足够用了,因为它获取到的就是客户端的真实IP地址。但是最近由于一些需求,开始使用Cloudflare的CDN服务,发现NPM中获取到的$remote_addr变成了Cloudflare的节点IP地址,而不是客户端的真实IP地址。

很多教程都是直接在每个反代配置中添加set_real_ip_fromreal_ip_header,如果你套CDN的站点比较少,那倒也无所谓,但是如果你有几十个站点都需要配置,那就非常麻烦了。经过一番研究,终于找到了一种统一的解决办法,只需要在NPM的全局配置中添加一行代码,就可以让所有的反代配置都能获取到客户端的真实IP地址。NPM支持使用自定义配置文件(实际上就是nginx的配置方法,NPM不过就是一个Nginx的管理面板而已)。

组件说明#

  • Nginx Proxy Manager:反向代理软件。
  • update_cf_ips.sh:更新Cloudflare的IP段信息到自定义nginx配置文件。

部署流程#

部署Nginx Proxy Manager#

  1. 参考这里,本文默认你也是Docker部署的NPM。

配置获取真实IP#

  1. 创建并复制粘贴update_cf_ips.sh脚本:
    Terminal window
    cd /root/docker_data/nginx && nano update_cf_ips.sh && chmod +x update_cf_ips.sh
    update_cf_ips.sh
    12 collapsed lines
    #!/bin/bash
    # ==============================================================================
    # Cloudflare IP Updater for Nginx Proxy Manager (NPM)
    # ==============================================================================
    # 功能:
    # 1. 自动从 Cloudflare 官方源获取最新的 IPv4 和 IPv6 地址列表。
    # 2. 生成 Nginx `real_ip` 配置,以正确获取通过 CF CDN 访问的真实用户 IP。
    # 3. 仅在 IP 列表发生变化时,才更新配置文件并重新加载 Nginx。
    # 4. 在无更新时,显示上次的更新时间。
    # ==============================================================================
    # --- 用户配置区 ---
    # Nginx Proxy Manager (NPM) 的自定义配置目录在宿主机上的绝对路径
    NPM_CUSTOM_DIR="/root/docker_data/nginx/data/nginx/custom"
    # NPM 的 Docker 容器名称或 ID
    NPM_CONTAINER_NAME="nginx-app-1"
    26 collapsed lines
    # --- 脚本核心逻辑 ---
    # --- 颜色定义 ---
    GREEN='\033[0;32m'
    YELLOW='\033[0;33m'
    RED='\033[0;31m'
    CYAN='\033[0;36m'
    RESET='\033[0m'
    # --- 日志函数 ---
    log_info() { echo -e " ${CYAN}*${RESET} $1"; }
    log_success() { echo -e " ${GREEN}✓ SUCCESS:${RESET} $1"; }
    log_warn() { echo -e " ${YELLOW}‼ WARN:${RESET} $1"; }
    log_error() { echo -e " ${RED}✗ ERROR:${RESET} $1" >&2; }
    # 脚本退出时执行的清理函数
    cleanup() {
    rm -f "$TMP_FILE"
    tput cnorm
    }
    # --- 主程序 ---
    trap cleanup EXIT
    set -e
    CONFIG_FILE_PATH="$NPM_CUSTOM_DIR/cloudflare_ips.conf"
    18 collapsed lines
    TMP_FILE=$(mktemp)
    echo -e "${GREEN}=====================================================${RESET}"
    echo -e "${CYAN} Cloudflare IP Updater for Nginx Proxy Manager${RESET}"
    echo -e "${GREEN}=====================================================${RESET}"
    echo -e "执行时间: $(date +"%Y-%m-%d %H:%M:%S")"
    # --- 步骤 1: 环境检查 ---
    echo -e "\n${CYAN}===[ 步骤 1/4: 环境检查 ]===${RESET}"
    log_info "检查自定义配置目录: $NPM_CUSTOM_DIR"
    if [ ! -d "$NPM_CUSTOM_DIR" ]; then
    log_error "目录不存在!请检查脚本中的 NPM_CUSTOM_DIR 变量。"
    exit 1
    fi
    log_success "目录存在。"
    log_info "检查网络下载工具 (curl/wget)..."
    if command -v curl &> /dev/null; then
    FETCH_CMD="curl -s -f -L"
    90 collapsed lines
    log_success "将使用 curl 进行下载。"
    elif command -v wget &> /dev/null; then
    FETCH_CMD="wget -qO-"
    log_success "将使用 wget 进行下载。"
    else
    log_error "系统中未找到 curl 或 wget,无法下载 IP 列表。"
    exit 1
    fi
    # --- 步骤 2: 下载并生成配置 ---
    echo -e "\n${CYAN}===[ 步骤 2/4: 下载并生成配置 ]===${RESET}"
    CF_IPV4_URL="https://www.cloudflare.com/ips-v4"
    CF_IPV6_URL="https://www.cloudflare.com/ips-v6"
    log_info "正在从 Cloudflare 下载最新的 IP 列表..."
    {
    echo "# Cloudflare IP Ranges"
    echo "# Auto-generated on $(date)"
    echo ""
    {
    $FETCH_CMD $CF_IPV4_URL
    echo ""
    $FETCH_CMD $CF_IPV6_URL
    } | sed '/^$/d' | sed 's/^/set_real_ip_from /; s/$/;/'
    echo ""
    echo "# 指定 Nginx 从 'CF-Connecting-IP' 请求头中获取真实的用户 IP 地址"
    echo "real_ip_header CF-Connecting-IP;"
    } > "$TMP_FILE"
    if [ $? -eq 0 ] && [ -s "$TMP_FILE" ]; then
    log_success "IP 列表下载并格式化完成。"
    else
    log_error "下载或处理 IP 列表失败,临时文件为空或下载出错。"
    exit 1
    fi
    # --- 步骤 3: 对比并更新配置 ---
    echo -e "\n${CYAN}===[ 步骤 3/4: 对比并更新配置 ]===${RESET}"
    # 【关键修改】这里的 log_info 消息被更新了
    log_info "对比新旧配置文件的核心内容..."
    get_core_config() {
    grep -E "set_real_ip_from|real_ip_header" "$1"
    }
    if [ ! -f "$CONFIG_FILE_PATH" ] || ! cmp -s <(get_core_config "$TMP_FILE") <(get_core_config "$CONFIG_FILE_PATH"); then
    log_success "检测到 IP 列表有更新 (或首次运行),准备更新配置文件。"
    mv "$TMP_FILE" "$CONFIG_FILE_PATH"
    log_success "配置文件已更新: $CONFIG_FILE_PATH"
    UPDATE_NEEDED=true
    else
    # 【关键修改】从旧文件中提取上次更新时间并显示
    last_update_time=$(grep "Auto-generated on" "$CONFIG_FILE_PATH" | sed 's/# Auto-generated on //')
    if [ -n "$last_update_time" ]; then
    # 如果成功提取到时间,就显示出来
    log_warn "Cloudflare IP 列表无变化。上次更新于: ${last_update_time}"
    else
    # 如果没找到时间戳行(以防万一),就显示通用消息
    log_warn "Cloudflare IP 列表无变化,无需更新。"
    fi
    UPDATE_NEEDED=false
    fi
    # --- 步骤 4: 重载 Nginx ---
    echo -e "\n${CYAN}===[ 步骤 4/4: 重载 Nginx 服务 ]===${RESET}"
    if [ "$UPDATE_NEEDED" = true ]; then
    log_info "正在测试 Nginx 配置..."
    if docker exec "$NPM_CONTAINER_NAME" nginx -t &> /dev/null; then
    log_success "Nginx 配置测试通过。"
    log_info "正在重新加载 Nginx 配置..."
    if docker exec "$NPM_CONTAINER_NAME" nginx -s reload &> /dev/null; then
    log_success "Nginx 配置已成功重新加载。"
    else
    log_error "Nginx reload 命令执行失败!"
    exit 1
    fi
    else
    log_error "新的 Nginx 配置测试失败!请检查 $CONFIG_FILE_PATH 文件内容。"
    exit 1
    fi
    else
    log_warn "无需重载 Nginx。"
    fi
    # --- 任务完成 ---
    echo -e "\n${GREEN}=====================================================${RESET}"
    echo -e "${GREEN} 🎉 脚本执行成功,任务完成! 🎉 ${RESET}"
    echo -e "${GREEN}=====================================================${RESET}"
    exit 0
  2. 设置crontab定时运行
    Terminal window
    crontab -e
    添加以下内容,每天凌晨2点运行一次:
    Terminal window
    # 每周一凌晨3点,自动更新 Nginx Proxy Manager 的 Cloudflare IP 列表
    0 3 * * 1 /root/docker_data/nginx/update_cf_ips.sh >> /var/log/update_cf_ips.log 2>&1

    记得修改脚本地址为你实际的脚本地址

  3. 手动运行脚本测试
    Terminal window
    ./update_cf_ips.sh && ls -alh /root/docker_data/nginx/data/nginx/custom/cloudflare_ips.conf
  4. 最后前往NPM面板,在你套了Cloudflare CDN的反代配置中,Advanced Tab下的Custom Nginx Configuration里添加一行代码:
    include /data/nginx/custom/cloudflare_ips.conf;
  5. 结束。至此,所有套了CF CDN的网站,都能获取到真实IP,而不需要繁杂的单独配置了。其他CDN提供商也可以参考同样的思路。
最后更新于 2025-10-28,距今已过 19 天

部分内容可能已过时

评论区

目录