nginx vts结合geoip,可对国家、城市限制、限流访问,并实时记录servername、国家、城市等的访问量和流量。

Nginx VTS docker build

由于官方镜像不支持第三方模块vts,所以我们这里要通过官方的方法build。 参考官方文档。 我们这里使用官方的老方法,介意的同学可使用上面的最新方法。 请按以下结构创建目录,各目录最后一个均为文件。

nginx-vts/
├── docker-compose.yml
├── modules
│   ├── Dockerfile
│   └── vts
│       └── source

docker-compose.yml

version: "3.3"
services:
  web:
    build:
      context: ./modules/
      args:
        ENABLED_MODULES: vts geoip
    image: nginx-vts:1.23.0-alpine

Dockerfile

FROM nginx:mainline as builder

ARG ENABLED_MODULES

RUN set -ex \
    && if [ "$ENABLED_MODULES" = "" ]; then \
        echo "No additional modules enabled, exiting"; \
        exit 1; \
    fi

COPY ./ /modules/

RUN set -ex \
    && apt update \
    && apt install -y --no-install-suggests --no-install-recommends \
                patch make wget mercurial devscripts debhelper dpkg-dev \
                quilt lsb-release build-essential libxml2-utils xsltproc \
                equivs git g++ libparse-recdescent-perl \
    && XSLSCRIPT_SHA512="f7194c5198daeab9b3b0c3aebf006922c7df1d345d454bd8474489ff2eb6b4bf8e2ffe442489a45d1aab80da6ecebe0097759a1e12cc26b5f0613d05b7c09ffa *stdin" \
    && wget -O /tmp/xslscript.pl https://hg.nginx.org/xslscript/raw-file/01dc9ba12e1b/xslscript.pl \
    && if [ "$(cat /tmp/xslscript.pl | openssl sha512 -r)" = "$XSLSCRIPT_SHA512" ]; then \
        echo "XSLScript checksum verification succeeded!"; \
        chmod +x /tmp/xslscript.pl; \
        mv /tmp/xslscript.pl /usr/local/bin/; \
    else \
        echo "XSLScript checksum verification failed!"; \
        exit 1; \
    fi \
    && hg clone -r ${NGINX_VERSION}-${PKG_RELEASE%%~*} https://hg.nginx.org/pkg-oss/ \
    && cd pkg-oss \
    && mkdir /tmp/packages \
    && for module in $ENABLED_MODULES; do \
        echo "Building $module for nginx-$NGINX_VERSION"; \
        if [ -d /modules/$module ]; then \
            echo "Building $module from user-supplied sources"; \
            # check if module sources file is there and not empty
            if [ ! -s /modules/$module/source ]; then \
                echo "No source file for $module in modules/$module/source, exiting"; \
                exit 1; \
            fi; \
            # some modules require build dependencies
            if [ -f /modules/$module/build-deps ]; then \
                echo "Installing $module build dependencies"; \
                apt update && apt install -y --no-install-suggests --no-install-recommends $(cat /modules/$module/build-deps | xargs); \
            fi; \
            # if a module has a build dependency that is not in a distro, provide a
            # shell script to fetch/build/install those
            # note that shared libraries produced as a result of this script will
            # not be copied from the builder image to the main one so build static
            if [ -x /modules/$module/prebuild ]; then \
                echo "Running prebuild script for $module"; \
                /modules/$module/prebuild; \
            fi; \
            /pkg-oss/build_module.sh -v $NGINX_VERSION -f -y -o /tmp/packages -n $module $(cat /modules/$module/source); \
            BUILT_MODULES="$BUILT_MODULES $(echo $module | tr '[A-Z]' '[a-z]' | tr -d '[/_\-\.\t ]')"; \
        elif make -C /pkg-oss/debian list | grep -P "^$module\s+\d" > /dev/null; then \
            echo "Building $module from pkg-oss sources"; \
            cd /pkg-oss/debian; \
            make rules-module-$module BASE_VERSION=$NGINX_VERSION NGINX_VERSION=$NGINX_VERSION; \
            mk-build-deps --install --tool="apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes" debuild-module-$module/nginx-$NGINX_VERSION/debian/control; \
            make module-$module BASE_VERSION=$NGINX_VERSION NGINX_VERSION=$NGINX_VERSION; \
            find ../../ -maxdepth 1 -mindepth 1 -type f -name "*.deb" -exec mv -v {} /tmp/packages/ \;; \
            BUILT_MODULES="$BUILT_MODULES $module"; \
        else \
            echo "Don't know how to build $module module, exiting"; \
            exit 1; \
        fi; \
    done \
    && echo "BUILT_MODULES=\"$BUILT_MODULES\"" > /tmp/packages/modules.env

FROM nginx:mainline
COPY --from=builder /tmp/packages /tmp/packages
RUN set -ex \
    && apt update \
    && . /tmp/packages/modules.env \
    && for module in $BUILT_MODULES; do \
           apt install --no-install-suggests --no-install-recommends -y /tmp/packages/nginx-module-${module}_${NGINX_VERSION}*.deb; \
       done \
    && rm -rf /tmp/packages \
    && rm -rf /var/lib/apt/lists/

source

文件内容为安装包互联网地址

https://github.com/vozlt/nginx-module-vts/archive/refs/tags/v0.2.2.tar.gz

build

回到目录nginx-vts,执行

docker-compose build

等待镜像编译。提示FINISHED编译完成。 并且在镜像列表中可以看见。

Nginx VTS docker start

启动前准备

下载国家城市数据

cd /data/nginx/geoip/
wget https://src.fedoraproject.org/lookaside/pkgs/GeoIP/GeoIP.dat.gz/4bc1e8280fe2db0adc3fe48663b8926e/GeoIP.dat.gz
gunzip GeoIP.dat.gz
wget https://src.fedoraproject.org/lookaside/pkgs/GeoIP/GeoLiteCity.dat.gz/2ec4a73cd879adddf916df479f3581c7/GeoLiteCity.dat.gz
gunzip  GeoLiteCity.dat.gz

docker-compose

  nginx:
    image: nginx-vts:1.23.0-alpine
    container_name: nginx
    ports:
       - "80:80"
       - "443:443"
    restart: always
    volumes:
      - /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf
      - /data/nginx/logs:/etc/nginx/logs/
      - /data/nginx/cert:/etc/nginx/cert/
      - /data/nginx/html:/var/www/html/:rw
      - /data/nginx/geoip:/etc/nginx/geoip
      - /etc/localtime:/etc/localtime

nginx.conf

load_module modules/ngx_http_vhost_traffic_status_module.so;
load_module modules/ngx_http_geoip_module.so;

events {
    ...
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    geoip_country /etc/nginx/geoip/GeoIP.dat;
    geoip_city /etc/nginx/geoip/GeoLiteCity.dat;
    vhost_traffic_status_zone;
    vhost_traffic_status_filter_by_set_key $geoip_country_code country::*;
    ...

    server {
        listen       80;
        server_name  localhost;
        access_log logs/host.access.log main;
        error_log logs/host.error.log  notice;

        location /status {
            vhost_traffic_status_display;
            vhost_traffic_status_display_format html;
        }

        location /where {
            default_type 'text/plain';
            return 200 "$remote_addr $geoip_country_name $geoip_country_code $geoip_city";
        }
    }

    server {
        listen       80;
        server_name  xxx.com;

        vhost_traffic_status_filter_by_set_key $geoip_country_code country::$server_name;
        ...
    }
}

浏览器访问: http://IP/status nginx运行状态,可看到国家访问情况。 http://IP/where 打印客户端浏览器所在国家和城市。

启动nginx

回到docker-compose.yml所在目录

docker-compose up -d

安装nginx-vts导出器

docker-compose

注意:不要使用docker安装,请到github下载二进制程序运行。

#X86
wget https://github.com/hnlq715/nginx-vts-exporter/releases/download/v0.10.8/nginx-vtx-exporter_0.10.8_linux_amd64.tar.gz
#ARM
wget https://github.com/hnlq715/nginx-vts-exporter/releases/download/v0.10.8/nginx-vtx-exporter_0.10.8_linux_arm64.tar.gz
tar zxvf nginx-vtx-exporter_0.10.8_linux_arm64.tar.gz 
nohup ./nginx-vtx-exporter -nginx.scrape_uri=http://localhost/status/format/json >/dev/null 2>&1 &
curl http://localhost:9913/metrics

prometheus配置

prometheus.yml

添加

  - job_name: 'nginx'
    static_configs:
    - targets: ['IP:9913']

重启prometheus

docker restart prometheus

grafana配置

导入模版编号:2949 注:其他nginx vts模版不兼容本安装方式,请不要导入。

告警规则

暂无

参考文档

https://github.com/hnlq715/nginx-vts-exporter https://github.com/nginxinc/docker-nginx/tree/master/modules https://github.com/vozlt/nginx-module-vts/ https://grafana.com/grafana/dashboards/2949-nginx-vts-stats/