手动编译安装宝塔nginx

手动编译安装宝塔nginx,以扩展一些其它模块,比如secure_link模块。

进入宝塔面板的安装文件夹: 打开终端,进入宝塔面板的安装目录,通常路径为 /www/server/panel/install/

cd  /www/server/panel/install/
wget http://download.bt.cn/install/0/nginx.sh

vim nginx.sh

在 nginx.sh 文件中,找到用于配置编译选项的部分(通常是以 ./configure 开头的行)。在该行的末尾添加:

--with-http_secure_link_module

以启用 secure_link 模块。

执行:

bash nginx.sh install 1.24

运行以下命令查看编译是否成功:

/www/server/nginx/sbin/nginx -V

高并发场景下的nginx优化

以nginx分发hls直播切片为例,对nginx高并发进行优化设置。

以下示例是nginx反代hls直播切片,每个m3u8包含5个ts切片,每个ts切片市场6s左右。本人使用的是4核8G的vps。

  1. worker_connections

    来自deepseek的说法,针对不同配置worker_connections的建议值:

    服务器配置推荐参数值
    4核8G,10Gbps网络worker_connections=32768
    8核16G,25Gbps网络worker_connections=65535
    32核64G,100Gbps网络worker_rlimit_nofile=262144

    2. worker_rlimit_nofile

    worker_rlimit_nofile = worker_connections × 2 + 安全余量

    worker_rlimit_nofile 70000;  # 32768×2=65536,取整为7万

    3. 修改 /etc/sysctl.conf

    # 文件描述符和连接队列
    fs.file-max = 1048576
    net.core.somaxconn = 65535
    net.ipv4.tcp_max_syn_backlog = 65535
    
    # TCP协议栈优化
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_fin_timeout = 30
    net.ipv4.tcp_keepalive_time = 120
    net.ipv4.tcp_max_orphans = 32768
    
    # 网络缓冲区
    net.core.rmem_max = 16777216
    net.core.wmem_max = 16777216
    net.ipv4.tcp_rmem = 4096 87380 16777216
    net.ipv4.tcp_wmem = 4096 65536 16777216

    4. 修改 /etc/security/limits.conf

    * soft nofile 1048576
    * hard nofile 1048576
    nginx soft nofile 1048576   # 如果以nginx用户运行
    nginx hard nofile 1048576

    6. 针对timeout的优化

    优化连接超时时间,以防止长时间占用连接让vps资源耗尽。

    http {
        # 请求头超时(默认60s)
        client_header_timeout 10s;    # 建议值:5~15秒
    
        # 请求体超时(默认60s)
        client_body_timeout 10s;      # 建议值:5~15秒(HLS无请求体,可缩短)
    
        # 发送响应超时(默认60s)
        send_timeout 20s;            # 建议值:20~60秒
    
        # 超时后重置连接(默认off)
        reset_timedout_connection on; # 强制开启
    }

    7. keepalive_requests

    定义:单个 TCP 连接最多允许处理多少个 HTTP 请求,超过后强制关闭连接。

    本质:控制连接的复用次数(生命周期内的总请求数)。

    类比:类似于“一根电话线最多允许通话1000次,之后必须换新线”。

    keepalive_requests 5000;     # 单个连接最多处理500个请求

    8. 启用 HTTP/2

    多路复用特性可显著减少 TCP 连接数,降低对 keepalive 配置的依赖:

    listen 443 ssl http2;

    keepalive_timeout:在HTTP/2中仍有效,但仅在连接完全空闲时触发。

    keepalive_requests:在HTTP/2中通常被忽略,连接生命周期由协议自身管理。

    9. limit_conn并发连接数优化

    limit_conn_zone $binary_remote_addr zone=addr:10m;  # 定义共享内存区(10MB)存储IP连接状态
    limit_conn addr 6;  # 每个IP最多允许8个并发TCP连接

    limit_conn_zone用于定义共享内存区域来存储连接状态,这里用$binary_remote_addr作为键,表示客户端的IP地址。zone=addr:10m分配了10MB的内存空间。limit_conn addr 8则是限制每个IP同时活跃的连接数为8。这里的“连接数”指的是同一时间的TCP连接,而不是请求数。每个HTTP请求可能复用同一个连接(在keepalive开启的情况下),但HLS的情况下,由于需要不断获取m3u8和ts,可能会有多个并发连接。

    连接数估算
    单播放器连接数:通常为 1(m3u8) + N(并行ts下载)。

    例如:若播放器并行下载2个 ts 切片,则占用 1+2=3 个连接。

    IP连接上限:若 limit_conn addr 6,则单个IP最多支持约 6/3=2 个播放器。

    worker_processes auto;  # 自动匹配CPU核心数
    worker_rlimit_nofile 70000; # 允许每个worker打开的最大文件数
    events {
        worker_connections 32768; # 每个worker的最大连接数
        use epoll; # 使用epoll高效I/O模型(Linux)
        multi_accept on; # 一次接受所有新连接
    }
    http {
        sendfile on; # 零拷贝传输静态文件
        tcp_nopush on; # 合并数据包减少网络开销
        tcp_nodelay on; # 禁用Nagle算法
        keepalive_timeout 15; # 保持连接的超时时间
        client_header_timeout 10; # 客户端请求头超时
        client_body_timeout 10; # 客户端请求体超时
        send_timeout 20; # 响应超时时间
        reset_timedout_connection on; # 超时后重置连接
    
        # 限制单个IP的并发连接数
        limit_conn_zone $binary_remote_addr zone=addr:10m;
        limit_conn addr 6; # 每个IP最多100个连接
    }

    最后,重启是配置生效

    sysctl -p   # 重新加载所有sysctl.conf中的配置
    
    # 根据系统服务管理工具选择命令
    systemctl restart nginx    # Systemd

    Linux安装ffmpeg、N_m3u8DL-RE推流mpd

    根据你的服务器架构选择,下面以 Linux 64 为例

    sudo apt update
    sudo apt install ffmpeg
    
    mkdir stream
    cd stream
    wget https://github.com/nilaoda/N_m3u8DL-RE/releases/download/v0.3.0-beta/N_m3u8DL-RE_v0.3.0-beta_linux-x64_20241203.tar.gz
    tar -zxvf N_m3u8DL-RE_v0.3.0-beta_linux-x64_20241203.tar.gz
    
    wget https://github.com/shaka-project/shaka-packager/releases/download/v3.4.1/packager-linux-x64
    
    chmod +x N_m3u8DL-RE packager-linux-x64

    推流:

    RE_LIVE_PIPE_OPTIONS="-c copy -f hls -hls_time 6 -hls_list_size 5 -hls_flags delete_segments+append_list jade.m3u8" ./N_m3u8DL-RE https://168itw.com/J --key "111:222" --concurrent-download true --append-url-params true --live-keep-segments false --del-after-done true --select-video best --select-audio all --use-shaka-packager true --mp4-real-time-decryption true --decryption-binary-path "./packager-linux-x64" --ui-language "zh-CN" --live-pipe-mux

    新入手VPS后需要的操作

    趁着黑5,又买了几台新的vps,虽然今年黑5整体折扣都很一般,没有往年大。

    记录一下我新入手vps后,常用的一些操作。这里是以建站、跑项目为例,vps用处不同可能操作也不一样。

    一、DD纯净debian系统

    这里根据自己需要看是否要dd,低配置的小鸡我一般会dd,配置高IPv4、v6双栈的vps,我一般也不dd。

    然后执行apt update。

    二、开启bbr加速

    三、安装宝塔/aapanel,安装nginx、php、mysql等

    根据自己需要选择是否安装aapanel等面板程序。如果你的网站需要用到防盗链鉴权,还需要给nginx编译编译secure_link模块。

    四、设置nginx使其获取到访客真实IP

    我喜欢套cloudflare,所以有必要从cloudflare获取访客真实IP。

    五、nginx屏蔽censys等爬虫

    六、防止各种日志log占满硬盘空间

    docker设置参考:https://www.168itw.com/tech/docker-log-opts/

    其它设置:https://www.168itw.com/tech/mysql-bin/

    七、添加cloudflare防火墙规则

    添加网站套上cloudflare后,及时给网站加上cloudflare防火墙,以阻止海量的恶意爬虫。

    修改SRS控制台显示的stream和client数目

    SRS是一款优秀的开源推流程序,GitHub上star的用户挺多的。

    SRS控制台默认只显示10条视频流和客户端,怎么修改让其显示更多呢?

    只需修改objs/nginx/html/console/js/srs.console.js,找到下面的代码,添加 url +=’&count=200′;

    streams_get: function(success) {
    var url = $sc_server.jsonp("/api/v1/streams/");
    url +='&count=200';
    $http.jsonp(url).success(success);
    },
    streams_get2: function(id, success) {
    var url = $sc_server.jsonp("/api/v1/streams/" + id);
    $http.jsonp(url).success(success);
    },
    clients_get: function(success) {
    var url = $sc_server.jsonp("/api/v1/clients/");
    url +='&count=200';
    $http.jsonp(url).success(success);
    },

    其中的200表示显示数目,可以根据自己的需要修改。

    修改代码之前,还需要给SRS docker安装vim:

    apt-get update
    
    apt-get install apt-file
    
    apt-file update
    
    apt-get install vim 

    打开srs.console.js添加代码后,保存退出,刷新SRS控制台,即可看到200条客户端和视频流了。

    以下为vim常用命令:

    i -- 切换到输入模式,在光标当前位置开始输入文本。
    x -- 删除当前光标所在处的字符。
    : -- 切换到底线命令模式,以在最底一行输入命令。
    a -- 进入插入模式,在光标下一个位置开始输入文本。
    o:在当前行的下方插入一个新行,并进入插入模式。
    O -- 在当前行的上方插入一个新行,并进入插入模式。
    dd -- 剪切当前行。
    yy -- 复制当前行。
    p(小写) -- 粘贴剪贴板内容到光标下方。
    P(大写)-- 粘贴剪贴板内容到光标上方。
    u -- 撤销上一次操作。
    Ctrl + r -- 重做上一次撤销的操作。
    :w -- 保存文件。
    :q -- 退出 Vim 编辑器。
    :q! -- 强制退出Vim 编辑器,不保存修改。

    在命令模式下按下 i 就进入了输入模式,使用 Esc 键可以返回到普通模式。

    在输入模式中,可以使用以下按键:

    字符按键以及Shift组合,输入字符
    ENTER,回车键,换行
    BACK SPACE,退格键,删除光标前一个字符
    DEL,删除键,删除光标后一个字符
    方向键,在文本中移动光标
    HOME/END,移动光标到行首/行尾
    Page Up/Page Down,上/下翻页
    Insert,切换光标为输入/替换模式,光标将变成竖线/下划线
    ESC,退出输入模式,切换到命令模式

    搭建btcloud宝塔云端

    btcloud是一款开源的宝塔云端程序,简单说就是:有了btcloud,你安装宝塔,安装宝塔插件(免费和付费),都不再需要跟宝塔官方通信了,btcloud接管了所有的官方通信,可以把btcloud理解成宝塔server端,你在其它vps上安装宝塔,就都是与此btcloud通信,使用此btcloud脚本。

    Github:https://github.com/flucont/btcloud

    那么,通过btcloud为什么能够安装宝塔的企业收费插件呢?

    那是因为btcloud后台绑定宝塔企业账号后,可以将所有插件都缓存到本地。所以要搭建btcloud,你还需要有一个宝塔企业账号。当然也可以用别人搭建好的btcloud来绑定(https://install.baota.sbs/),实现循环套娃;也有人说可以用bt.sy来套娃,不过我没有试验过。

    以下记录搭建btcloud的过程。

    一、用一台小鸡来搭建btcloud

    配置要求可以参看GitHub说明,下载最新release包到对应目录,解压,设置网站运行目录为public,设置伪静态为ThinkPHP,访问网站,会自动跳转到安装页面,根据提示安装完成。

    如果是用惯了宝塔的小白,不会上述过程,其实你也可以先在小鸡上安装宝塔官方版本或者aapanel,通过aapanel来配置环境部署btcloud,你也可以绑定一个域名,比如bt.168itw.com来访问btcloud程序。

    二、登录btcloud后台(比如 bt.168itw.com/admin),执行相关操作

    1. 系统设置 – 替换与清理工具,复制相关命令,在安装btcloud的vps的ssh客户端上执行;
    2. 系统设置 – 面板接口设置,这里就需要设置绑定你的宝塔企业账号,用于btcloud缓存插件,如果没有企业账号,可以选择对接第三方云端(比如https://install.baota.sbs/等),测试通过后,保存;
    3. 系统设置 – 自动更新插件设置,先设置需要下载的插件范围,然后复制相关命令,去安装btcloud的vps ssh执行,缓存宝塔插件到本地,后期可以通过添加到crontab命令来自动同步插件;
    4. 其它设置:系统设置 – 软件版本设置,来设置白名单,以及是否开启脚本展示页面等。

    至此,btcloud就安装完成了,访问/download页面,查看自己的宝塔装脚本。现在你就可以在任意vps上运行该脚本来安装宝塔,并且安装付费的插件了。

    daemon.json配置docker容器日志大小及错误排查

    docker日志目录:/var/lib/docker/containers/<容器id>/

    docker容器的运行日志,如果不加以限制,会越来越大,占用非常大的磁盘空间。可以通过daemon.json配置docker日志文件大小,全局有效。

        docker安装后默认没有daemon.json这个配置文件,需要进行手动创建,docker不管是在哪个平台以何种方式启动, 默认都会来这里读取配置,使用户可以统一管理不同系统下的 docker daemon 配置。
    
        如果在daemon.json文件中进行配置,需要docker版本高于1.12,配置文件的默认径为:/etc/docker/daemon.json      
    
        该文件作为 Docker Engine 的配置管理文件, 里面几乎涵盖了所有 docker 命令行启动可以配置的参数。

    如果没有daemon.json,新建一个,添加以下内容:

    {
    "exec-opts": [""],
    "log-driver":"json-file",
     "log-opts": {
       "max-size": "300m",
       "max-file": "1"
     }
    }

    然后重启docker守护进程:

    systemctl daemon-reload
    systemctl restart docker

    如果docker无法启动报错,使用dockerd查看输出错误信息:

    dockerd

    在网上看到docker无法启动后,systemctl status docker.service、cat /lib/systemd/system/docker.service等等,各种排查,其实都不能有效的找出错误原因,只有dockerd才是输出有效的错误信息。

    另外需要注意,改动了daemon.json后,都一定是要运行systemctl daemon-reload和systemctl restart docker来重启docker。

    如果是docker-compose来运行容器的,也可以在 docker-compose.yml 中添加:

    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    

    APISIX网关部署使用教程

    APISIX是一个具有动态、实时、高性能等特点的云原生 API 网关。你可以使用 APISIX 网关作为所有业务的流量入口,它提供了动态路由、动态上游、动态证书、A/B 测试、灰度发布(金丝雀发布)、蓝绿部署、限速、防攻击、收集指标、监控报警、可观测、服务治理等功能。

    安装APISIX

    部署apisix最简单的方法就是docker部署,直接使用官方的example配置。

    git clone https://github.com/apache/apisix-docker.git
    cd apisix-docker/example

    example下的docker-compose.yml和docker-compose-arm64.yml分别对应的是X86和ARM服务器。

    查看yml文件会发现,会启动了多个docker服务:

    • apisix:主程序,api网关;
    • etcd:APISIX 使用 etcd 作为配置中心进行保存和同步配置;
    • prometheus:开源的监控程序;
    • grafana:开源的看板程序;

    web1和web2是测试程序,可以直接去掉。

    另外,如果我们要使用apisix的UI控制面板,可以在docker-compose.yml中再加一个apisix-dashboard的docker服务:

      apisix-dashboard:
        image: apache/apisix-dashboard:3.0.1-alpine
        restart: always
        volumes:
        - ./dashboard_conf/conf.yaml:/usr/local/apisix-dashboard/conf/conf.yaml
        ports:
        - "9000:9000"
        networks:
          apisix:

    最终的docker-compose.yml文件为:

    #
    # Licensed to the Apache Software Foundation (ASF) under one or more
    # contributor license agreements.  See the NOTICE file distributed with
    # this work for additional information regarding copyright ownership.
    # The ASF licenses this file to You under the Apache License, Version 2.0
    # (the "License"); you may not use this file except in compliance with
    # the License.  You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    #
    
    version: "3"
    
    services:
      apisix-dashboard:
        image: apache/apisix-dashboard:3.0.1-alpine
        restart: always
        volumes:
        - ./dashboard_conf/conf.yaml:/usr/local/apisix-dashboard/conf/conf.yaml
        ports:
        - "9000:9000"
        networks:
          apisix:
    
      apisix:
        image: apache/apisix:${APISIX_IMAGE_TAG:-3.6.0-debian}
        restart: always
        volumes:
          - ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml:ro
        depends_on:
          - etcd
        ##network_mode: host
        ports:
          - "9180:9180/tcp"
          - "9080:9080/tcp"
          - "9091:9091/tcp"
          - "9443:9443/tcp"
          - "9092:9092/tcp"
        networks:
          apisix:
    
      etcd:
        image: bitnami/etcd:3.4.15
        restart: always
        volumes:
          - etcd_data:/bitnami/etcd
        environment:
          ETCD_ENABLE_V2: "true"
          ALLOW_NONE_AUTHENTICATION: "yes"
          ETCD_ADVERTISE_CLIENT_URLS: "http://etcd:2379"
          ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
        ports:
          - "2379:2379/tcp"
        networks:
          apisix:
    
      prometheus:
        image: prom/prometheus:v2.25.0
        restart: always
        volumes:
          - ./prometheus_conf/prometheus.yml:/etc/prometheus/prometheus.yml
        ports:
          - "9090:9090"
        networks:
          apisix:
    
      grafana:
        image: grafana/grafana:7.3.7
        restart: always
        ports:
          - "3000:3000"
        volumes:
          - "./grafana_conf/provisioning:/etc/grafana/provisioning"
          - "./grafana_conf/dashboards:/var/lib/grafana/dashboards"
          - "./grafana_conf/config/grafana.ini:/etc/grafana/grafana.ini"
        networks:
          apisix:
    
    networks:
      apisix:
        driver: bridge
    
    volumes:
      etcd_data:
        driver: local
    

    通过修改本地example/dashboard_conf/conf.yaml 文件,来修改控制面板的配置。需要修改users中的用户名和密码,用于登录控制面板。

    #
    # Licensed to the Apache Software Foundation (ASF) under one or more
    # contributor license agreements.  See the NOTICE file distributed with
    # this work for additional information regarding copyright ownership.
    # The ASF licenses this file to You under the Apache License, Version 2.0
    # (the "License"); you may not use this file except in compliance with
    # the License.  You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    #
    
    conf:
      listen:
        host: 0.0.0.0     # `manager api` listening ip or host name
        port: 9000          # `manager api` listening port
      allow_list:           # If we don't set any IP list, then any IP access is allowed by default.
        - 0.0.0.0/0
      etcd:
        endpoints:          # supports defining multiple etcd host addresses for an etcd cluster
          - "http://etcd:2379"
                              # yamllint disable rule:comments-indentation
                              # etcd basic auth info
        # username: "root"    # ignore etcd username if not enable etcd auth
        # password: "123456"  # ignore etcd password if not enable etcd auth
        mtls:
          key_file: ""          # Path of your self-signed client side key
          cert_file: ""         # Path of your self-signed client side cert
          ca_file: ""           # Path of your self-signed ca cert, the CA is used to sign callers' certificates
        # prefix: /apisix     # apisix config's prefix in etcd, /apisix by default
      log:
        error_log:
          level: warn       # supports levels, lower to higher: debug, info, warn, error, panic, fatal
          file_path:
            logs/error.log  # supports relative path, absolute path, standard output
                            # such as: logs/error.log, /tmp/logs/error.log, /dev/stdout, /dev/stderr
        access_log:
          file_path:
            logs/access.log  # supports relative path, absolute path, standard output
                             # such as: logs/access.log, /tmp/logs/access.log, /dev/stdout, /dev/stderr
                             # log example: 2020-12-09T16:38:09.039+0800	INFO	filter/logging.go:46	/apisix/admin/routes/r1	{"status": 401, "host": "127.0.0.1:9000", "query": "asdfsafd=adf&a=a", "requestId": "3d50ecb8-758c-46d1-af5b-cd9d1c820156", "latency": 0, "remoteIP": "127.0.0.1", "method": "PUT", "errs": []}
      security:
          # access_control_allow_origin: "http://httpbin.org"
          # access_control_allow_credentials: true          # support using custom cors configration
          # access_control_allow_headers: "Authorization"
          # access_control-allow_methods: "*"
          # x_frame_options: "deny"
          content_security_policy: "default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; frame-src *"  # You can set frame-src to provide content for your grafana panel.
    
    authentication:
      secret:
        secret              # secret for jwt token generation.
                            # NOTE: Highly recommended to modify this value to protect `manager api`.
                            # if it's default value, when `manager api` start, it will generate a random string to replace it.
      expire_time: 3600     # jwt token expire time, in second
      users:                # yamllint enable rule:comments-indentation
        - username: username   # username and password for login `manager api`
          password: password
    
    plugins:                          # plugin list (sorted in alphabetical order)
      - api-breaker
      - authz-keycloak
      - basic-auth
      - batch-requests
      - consumer-restriction
      - cors
      # - dubbo-proxy
      - echo
      # - error-log-logger
      # - example-plugin
      - fault-injection
      - grpc-transcode
      - hmac-auth
      - http-logger
      - ip-restriction
      - jwt-auth
      - kafka-logger
      - key-auth
      - limit-conn
      - limit-count
      - limit-req
      # - log-rotate
      # - node-status
      - openid-connect
      - prometheus
      - proxy-cache
      - proxy-mirror
      - proxy-rewrite
      - redirect
      - referer-restriction
      - request-id
      - request-validation
      - response-rewrite
      - serverless-post-function
      - serverless-pre-function
      # - skywalking
      - sls-logger
      - syslog
      - tcp-logger
      - udp-logger
      - uri-blocker
      - wolf-rbac
      - zipkin
      - server-info
      - traffic-split
    

    运行docker compose启动docker:

    docker-compose -p docker-apisix up -d

    配置APISIX

    通过修改本地 ./conf/config.yaml 文件,完成对 APISIX 服务本身的基本配置。建议修改 Admin API 的key,保护 APISIX 的安全。同时可以限制IP访问API,增加安全性:

    deployment:
      admin:
        allow_admin:               # https://nginx.org/en/docs/http/ngx_http_access_module.html#allow
          - 127.0.0.0/24              # We need to restrict ip access rules for security. 0.0.0.0/0 is for test.
          - 本机IP
    
        admin_key:
          - name: "admin"
            key: newpassword
            role: admin                 # admin: manage all configuration data

    上述限制IP的策略,主要是考虑apisix-dashboard控制面板来访问api,其它应用场合根据实际情况修改。

    使用APISIX

    访问http://ip:9000,用上述用户名和密码就可以登录API控制面板了。具体使用过程比较简单,这里不详述,只说下在使用容易踩坑的地方。

    apisix最常用的就是对访问进行限速控制,主要涉及到三个插件:

    • limit-conn:并发请求数
    • limit-count:指定时间窗口内的请求数量
    • limit-req:请求速率

    而限速又涉及到访客IP,只有获取到用户的真实IP才能有效地限速,所以这里就又涉及到real ip插件。

    1. APISIX官方文档中,说real IP插件需要重新编辑APISIX-Base,但实际上,现在新版本的apisix docker镜像,都已经是运行在APISIX-Base上的。
    2. APISIX传递real IP给上游,需要自行配置,plugin字段中添加如下代码:
        "real-ip": {
          "source": "http_x_forwarded_for",
          "trusted_addresses": [
            "0.0.0.0/0"
          ]
        }

    source必须为http_x_forwarded_for才有效,使用官方文档中的$remote_addr、$remote_port测试都无效,这是我踩过很久的坑。

    trusted_addresses为信任的回源IP,可以根据实际情况修改。比如,如果使用nginx反代了apisix网关,则trust IP是反代服务器IP:

        "real-ip": {
          "source": "http_x_forwarded_for",
          "trusted_addresses": [
            "反代服务器IP"
          ]
        }

    3. 在上述3个插件的配中,key的值必须为remote_addr,才能获取到访客真实IP,使用官方文档中的http_x_real_ip、http_x_forwarded_for都无效,也不知道是哪里的问题。

    4. 如果你的APISIX前面还运行了一层nginx,或者是还套了一层cloudflare(访客访问域名 – cloudflare CDN – nginx – APISIX),那么就需要递归传递用户的真实IP,特别注意的是因为apisix运行在docker,所以set_real_ip_from需要添加docker内网IP段:

    docker inspect 容器id
    set_real_ip_from 172.18.0.0/24

    可以参考前面的文章:https://www.168itw.com/web-server/cloudflare-cdn-real-ip/
    也可以参考:https://github.com/apache/apisix/discussions/4793

    其它更多功能还没有测试,后期继续补充完善该教程。

    使用cloudflare CDN的网站获取访客真实IP

    之前有一篇文章是介绍宝塔获取cloudflare CDN访客真实IP的文章,但是那篇文章比较粗糙。下面结合cloudflare官方的说明文档,做一些补充说明。

    一、CF-Connecting-IP 和 X-Forwarded-For

    cloudflare将原始访问者 IP 地址显示在名为 CF-Connecting-IP 和 X-Forwarded-For 的附加 HTTP 标头中。所以你可以选择用:

    real_ip_header CF-Connecting-IP; 

    或者:

    real_ip_header X-Forwarded-For;
    real_ip_recursive on;

    来获取访客真实IP。

    二、ngx_http_realip_module模块

    nginx服务器获取realip是依赖ngx_http_realip_module模块的,所以如果你用的是nginx,必须要编译ngx_http_realip_module模块。使用nginx -V命令查看nginx是否已经编译该模块,没有的话需要自己编译。

    其它服务器参考cloudflare官方说明文档

    三、set_real_ip_from的使用

    如果是 set_real_ip_from 0.0.0.0/0; 则表示信任所有前代理传递的真实用户ip,会有安全隐患,我们可以设置为只信任cloudflare的IP:

    server
    {
    listen 443 ssl http2;
    listen [::]:80;
    server_name 168itw.com;
    
    set_real_ip_from 103.21.244.0/22;
    set_real_ip_from 103.22.200.0/22;
    set_real_ip_from 103.31.4.0/22;
    set_real_ip_from 104.16.0.0/12;
    set_real_ip_from 108.162.192.0/18;
    set_real_ip_from 131.0.72.0/22;
    set_real_ip_from 141.101.64.0/18;
    set_real_ip_from 162.158.0.0/15;
    set_real_ip_from 172.64.0.0/13;
    set_real_ip_from 173.245.48.0/20;
    set_real_ip_from 188.114.96.0/20;
    set_real_ip_from 190.93.240.0/20;
    set_real_ip_from 197.234.240.0/22;
    set_real_ip_from 198.41.128.0/17;
    set_real_ip_from 2400:cb00::/32;
    set_real_ip_from 2606:4700::/32;
    set_real_ip_from 2803:f800::/32;
    set_real_ip_from 2405:b500::/32;
    set_real_ip_from 2405:8100::/32;
    set_real_ip_from 2c0f:f248::/32;
    set_real_ip_from 2a06:98c0::/29;
    
    #X-Forwarded-For和CF-Connecting-IP二选一
    real_ip_header    X-Forwarded-For;
    real_ip_recursive on;
    #real_ip_header CF-Connecting-IP; 
    

    cloudflare IP段:https://www.cloudflare.com/ips/

    注意:添加在nginx的http{}中,则全局应用在下面的所有server中,即所有网站生效;添加在网站对应的server{}中,则只有该网站中生效。

    特别注意:如果同时运行了docker,且有反代docker服务,则需要将docker内网IP段也要加到set_real_ip_from中。

    查看docker容器IP:

    docker inspect 容器id

    添加docker内网IP段:

    set_real_ip_from 172.18.0.0/24

    四、多级反向代理

    如果cloudflare之后还有多级反向代理,可以在cloudflare后的第一级反代只允许cf IP回源,后面的允许上一级反代IP回源。

    五、开启CLOUDFLARE的回源认证

    cloudflare后台 SSL/TLS – Overview:SSL/TLS encryption mode设置为Full或者Full (strict)

    SSL/TLS – Origin Server 开启:Authenticated Origin Pulls

    在对应主机的配置文件的server块内加入下列代码:

    ssl_client_certificate /etc/nginx/certs/cloudflare.pem;
    ssl_verify_client on;

    cloudflare.pem文件下载地址:https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/zone-level/

    继续阅读