上一篇 下一篇 分享链接 返回 返回顶部

自建“类 Cloudflare”边缘网关:从 HTTPS、WAF 到内网穿透的完整配置方案

发布人:慈云数据-客服中心 发布时间:23小时前 阅读量:4

Cloudflare 私有化部署方案|附配置文件

说明:严格来说,Cloudflare 是一个全球化 SaaS 平台,完整的 Cloudflare CDN、Anycast 网络、DDoS 清洗中心、WAF 规则体系无法被“私有化部署”到本地或自有服务器中。
本文所说的“Cloudflare 私有化部署方案”,指的是在企业自有服务器、VPS、IDC 或私有云环境中,搭建一套具备 反向代理、HTTPS 证书、访问控制、WAF 防护、限流、日志审计、内网服务暴露 等能力的“类 Cloudflare 网关方案”。


一、方案目标

在很多企业场景中,业务系统可能并不希望完全依赖公有云安全网关,原因包括:

  • 数据合规要求较高;
  • 内部系统不能直接暴露公网;
  • 希望掌握完整访问日志;
  • 希望自定义安全策略;
  • 希望降低长期 SaaS 成本;
  • 希望在多云、混合云、本地机房之间统一入口。

因此,我们可以通过自建边缘网关实现类似 Cloudflare 的部分能力。

本方案主要实现以下功能:

能力 自建方案
HTTPS 证书 Caddy / Nginx + ACME
反向代理 Nginx / Caddy / Traefik
WAF ModSecurity + OWASP CRS
访问控制 Basic Auth / IP 白名单 / OAuth2 Proxy
限流 Nginx limit_req
日志审计 Nginx 日志 + Prometheus / Loki
内网穿透 WireGuard / FRP / Cloudflare Tunnel
安全封禁 CrowdSec / Fail2ban
容器化部署 Docker Compose
统一入口 私有网关节点

二、整体架构设计

推荐架构如下:

用户浏览器
   │
   ▼
公网 DNS
   │
   ▼
自建边缘网关服务器
Nginx / Caddy / Traefik
   │
   ├── WAF:ModSecurity + OWASP CRS
   ├── TLS:Let's Encrypt / ZeroSSL
   ├── 限流:Nginx limit_req
   ├── 访问控制:IP 白名单 / OAuth2 Proxy
   ├── 日志审计:Loki / Prometheus
   │
   ▼
后端服务
应用服务器 / Kubernetes / 内网主机

如果后端服务没有公网 IP,可以增加一层内网隧道:

用户
 │
 ▼
公网网关
 │
 ▼
WireGuard / FRP / Cloudflare Tunnel
 │
 ▼
内网应用服务器

这个模式适合以下场景:

  • 家庭实验室服务暴露;
  • 企业内网 OA、GitLab、Jenkins、Wiki;
  • Kubernetes Ingress 外部入口;
  • 多个业务系统统一 HTTPS 出口;
  • 自建零信任访问网关。

三、服务器准备

建议准备一台公网服务器作为边缘网关。

最低配置:

CPU:2 核
内存:2 GB
磁盘:40 GB
系统:Ubuntu 22.04 / Debian 12
带宽:根据业务访问量决定

开放端口:

80/tcp    HTTP,用于证书签发和跳转
443/tcp   HTTPS 主入口
22/tcp    SSH 管理,可修改为非默认端口
51820/udp WireGuard,可选

安装基础组件:

apt update
apt install -y curl wget vim git ufw ca-certificates gnupg lsb-release

安装 Docker:

curl -fsSL https://get.docker.com | bash
systemctl enable docker
systemctl start docker

安装 Docker Compose:

apt install -y docker-compose-plugin

创建部署目录:

mkdir -p /opt/private-cloudflare
cd /opt/private-cloudflare

四、核心组件选择

本文采用以下组件:

组件 作用
Nginx 反向代理、HTTPS、限流
ModSecurity Web 应用防火墙
OWASP CRS 通用 WAF 规则集
Certbot 自动申请 HTTPS 证书
CrowdSec 行为分析与恶意 IP 封禁
WireGuard 内网安全隧道
Prometheus + Grafana 监控,可选
Loki 日志分析,可选

这里没有选择 Caddy 的原因是:Caddy 虽然自动 HTTPS 非常方便,但如果要集成 ModSecurity、复杂 WAF 策略和限流,Nginx 的生态更成熟。


五、Docker Compose 配置文件

创建 docker-compose.yml

version: "3.9"

services:
  nginx:
    image: owasp/modsecurity-crs:nginx
    container_name: private-edge-nginx
    restart: always
    ports:
      - "80:80"
      - "443:443"
    environment:
      PARANOIA: 1
      ANOMALY_INBOUND: 5
      ANOMALY_OUTBOUND: 4
      BLOCKING_PARANOIA: 1
      MODSEC_RULE_ENGINE: "On"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certbot/www:/var/www/certbot
      - ./certbot/conf:/etc/letsencrypt
      - ./logs/nginx:/var/log/nginx
    networks:
      - edge

  certbot:
    image: certbot/certbot
    container_name: private-edge-certbot
    volumes:
      - ./certbot/www:/var/www/certbot
      - ./certbot/conf:/etc/letsencrypt
    networks:
      - edge

  whoami:
    image: traefik/whoami
    container_name: demo-whoami
    restart: always
    networks:
      - edge

networks:
  edge:
    driver: bridge

这个配置包含三个服务:

  1. nginx:公网入口;
  2. certbot:证书申请工具;
  3. whoami:测试后端服务。

生产环境中,可以将 whoami 替换成自己的应用,例如 GitLab、Jenkins、企业后台等。


六、Nginx 主配置文件

创建目录:

mkdir -p nginx/conf.d certbot/www certbot/conf logs/nginx

创建 nginx/nginx.conf

user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 4096;
    multi_accept on;
}

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

    server_tokens off;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for" '
                    'rt=$request_time uct="$upstream_connect_time" '
                    'uht="$upstream_header_time" urt="$upstream_response_time"';

    access_log /var/log/nginx/access.log main;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    keepalive_timeout 65;
    client_max_body_size 50m;

    gzip on;
    gzip_disable "msie6";
    gzip_comp_level 5;
    gzip_min_length 1k;
    gzip_types text/plain text/css application/json application/javascript application/xml image/svg+xml;

    real_ip_header X-Forwarded-For;

    limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=10r/s;
    limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;

    include /etc/nginx/conf.d/*.conf;
}

七、站点反向代理配置

假设你的域名是:

demo.example.com

请先将域名 A 记录解析到这台网关服务器的公网 IP。

创建 nginx/conf.d/demo.example.com.conf

server {
    listen 80;
    server_name demo.example.com;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl http2;
    server_name demo.example.com;

    ssl_certificate /etc/letsencrypt/live/demo.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/demo.example.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;

    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    limit_req zone=req_limit_per_ip burst=20 nodelay;
    limit_conn conn_limit_per_ip 30;

    location / {
        proxy_pass http://whoami:80;

        proxy_http_version 1.1;

        proxy_set_header Host $host;
        proxy_set_header Real-IP $remote_addr;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_connect_timeout 10s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

首次启动前,由于证书文件还不存在,Nginx 可能无法正常加载 HTTPS 配置。可以先临时注释掉 443 server,申请证书后再恢复。


八、申请 HTTPS 证书

先启动 Nginx:

docker compose up -d nginx

申请证书:

docker compose run --rm certbot certonly \
  --webroot \
  --webroot-path=/var/www/certbot \
  --email admin@example.com \
  --agree-tos \
  --no-eff-email \
  -d demo.example.com

申请成功后,重启 Nginx:

docker compose restart nginx

访问:

https://demo.example.com

如果看到 whoami 返回信息,说明反向代理已经生效。


九、证书自动续期配置

创建续期脚本 renew-cert.sh

#!/bin/bash

cd /opt/private-cloudflare

docker compose run --rm certbot renew

docker compose exec nginx nginx -s reload

添加执行权限:

chmod +x renew-cert.sh

添加定时任务:

crontab -e

写入:

0 3 * * * /opt/private-cloudflare/renew-cert.sh >> /opt/private-cloudflare/logs/certbot-renew.log 2>&1

这样每天凌晨 3 点会尝试续期证书。如果证书未到期,Certbot 不会重复申请。


十、开启 WAF 防护

当前使用的镜像 owasp/modsecurity-crs:nginx 已经内置 ModSecurity 和 OWASP CRS。

环境变量中:

MODSEC_RULE_ENGINE: "On"
PARANOIA: 1
ANOMALY_INBOUND: 5
ANOMALY_OUTBOUND: 4

含义如下:

参数 说明
MODSEC_RULE_ENGINE 是否启用阻断模式
PARANOIA 检测等级,越高越严格
ANOMALY_INBOUND 入站异常分数阈值
ANOMALY_OUTBOUND 出站异常分数阈值

建议:

  • 初次上线:使用 DetectionOnly
  • 观察误报:分析日志;
  • 稳定后:切换为 On

例如,调试阶段可以改成:

MODSEC_RULE_ENGINE: "DetectionOnly"

这样 WAF 只记录攻击行为,不直接拦截请求。


十一、IP 白名单访问控制

对于后台系统,例如 Jenkins、GitLab Admin、内部管理后台,建议增加 IP 白名单。

示例配置:

location /admin/ {
    allow 1.2.3.4;
    allow 5.6.7.0/24;
    deny all;

    proxy_pass http://backend-admin:8080;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

如果你的管理员 IP 不固定,可以使用 VPN 方案,例如 WireGuard,让管理员先接入 VPN,再访问后台系统。


十二、Basic Auth 访问认证

为某些测试环境增加简单密码认证。

安装 htpasswd 工具:

apt install -y apache2-utils

创建密码文件:

mkdir -p nginx/auth
htpasswd -bc nginx/auth/basic.htpasswd admin 'StrongPasswordHere'

修改 docker-compose.yml,挂载认证文件:

volumes:
  - ./nginx/auth:/etc/nginx/auth

Nginx 配置增加:

location / {
    auth_basic "Private Area";
    auth_basic_user_file /etc/nginx/auth/basic.htpasswd;

    proxy_pass http://whoami:80;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Basic Auth 适合测试环境,不建议作为生产系统唯一认证方式。


十三、接入内网服务:WireGuard 方案

如果后端应用部署在公司内网或家中 NAS,没有公网 IP,可以使用 WireGuard 建立安全隧道。

1. 网关服务器安装 WireGuard

apt install -y wireguard

生成密钥:

wg genkey | tee server_private.key | wg pubkey > server_public.key

创建 /etc/wireguard/wg0.conf

[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT

[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.10.0.2/32

启动:

systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0

2. 内网客户端配置

内网服务器安装 WireGuard 后,创建客户端配置:

[Interface]
Address = 10.10.0.2/24
PrivateKey = CLIENT_PRIVATE_KEY

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = your-public-server-ip:51820
AllowedIPs = 10.10.0.0/24
PersistentKeepalive = 25

启动客户端后,公网网关就可以访问内网服务,例如:

http://10.10.0.2:8080

然后修改 Nginx 代理:

location / {
    proxy_pass http://10.10.0.2:8080;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

这样,用户访问公网域名时,实际请求会通过 WireGuard 隧道转发到内网应用。


十四、日志审计与安全分析

Nginx 日志会写入:

/opt/private-cloudflare/logs/nginx/access.log
/opt/private-cloudflare/logs/nginx/error.log

你可以直接查看:

tail -f logs/nginx/access.log

常见攻击请求包括:

/wp-admin
/.env
/phpmyadmin
/admin.php
/cgi-bin

如果日志中大量出现类似请求,可以结合 Fail2ban 或 CrowdSec 自动封禁。


十五、接入 CrowdSec 自动封禁

CrowdSec 可以分析 Nginx 日志,并自动识别扫描器、爆破攻击、恶意 IP。

安装 CrowdSec:

curl -s https://install.crowdsec.net | bash
apt install -y crowdsec

安装 Nginx collection:

cscli collections install crowdsecurity/nginx
systemctl reload crowdsec

安装防火墙 bouncer:

apt install -y crowdsec-firewall-bouncer-iptables

查看告警:

cscli alerts list

查看封禁决策:

cscli decisions list

这样可以实现类似 Cloudflare 防火墙规则和恶意 IP 拦截的部分能力。


十六、防火墙配置

使用 UFW 限制端口:

ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 51820/udp
ufw enable

如果 SSH 修改了端口,例如 2222:

ufw allow 2222/tcp
ufw delete allow 22/tcp

建议禁止密码登录 SSH。

修改 /etc/ssh/sshd_config

PasswordAuthentication no
PermitRootLogin no

重启 SSH:

systemctl restart ssh

十七、多个域名反向代理示例

如果你有多个系统,例如:

git.example.com
wiki.example.com
jenkins.example.com

可以分别创建配置文件。

GitLab 示例

server {
    listen 80;
    server_name git.example.com;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl http2;
    server_name git.example.com;

    ssl_certificate /etc/letsencrypt/live/git.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/git.example.com/privkey.pem;

    client_max_body_size 500m;

    location / {
        proxy_pass http://10.10.0.2:8929;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Wiki 示例

server {
    listen 80;
    server_name wiki.example.com;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl http2;
    server_name wiki.example.com;

    ssl_certificate /etc/letsencrypt/live/wiki.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/wiki.example.com/privkey.pem;

    location / {
        proxy_pass http://10.10.0.3:3000;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

十八、与 Cloudflare 官方能力对比

功能 Cloudflare 自建方案
全球 CDN 需要多节点自建
DDoS 防护 依赖服务器带宽和上游清洗
WAF 可用 ModSecurity/Coraza
HTTPS 可用 Certbot/Caddy
Tunnel 可用 WireGuard/FRP
访问控制 OAuth2 Proxy / Authelia
日志掌控 企业版更强 完全自控
成本 SaaS 订阅 服务器与维护成本
可定制化 有限制
运维复杂度 中高

自建方案的优势是自主可控、灵活度高;缺点是无法天然获得 Cloudflare 全球 Anycast 网络和超大规模 DDoS 清洗能力。


十九、生产环境建议

如果要用于生产环境,建议至少做到以下几点:

  1. 网关高可用
    至少部署两台边缘网关,通过 DNS 轮询、Keepalived 或负载均衡实现冗余。

  2. 日志集中化
    将 Nginx、WAF、系统日志统一接入 Loki、ELK 或 OpenSearch。

  3. 证书统一管理
    对大量域名建议使用 DNS-01 方式申请通配符证书。

  4. 安全策略分级
    普通业务走 WAF,后台系统走 VPN 或零信任认证。

  5. 定期更新规则
    OWASP CRS、Nginx、Docker 镜像应定期升级。

  6. 备份配置文件
    /opt/private-cloudflare 目录应纳入 Git 或备份系统。

  7. 限制源站访问
    后端应用只允许来自网关服务器或 WireGuard 网段访问,避免源站绕过安全网关。


二十、完整目录结构

最终目录结构如下:

/opt/private-cloudflare
├── docker-compose.yml
├── renew-cert.sh
├── nginx
│   ├── nginx.conf
│   ├── auth
│   │   └── basic.htpasswd
│   └── conf.d
│       ├── demo.example.com.conf
│       ├── git.example.com.conf
│       └── wiki.example.com.conf
├── certbot
│   ├── conf
│   └── www
└── logs
    ├── nginx
    │   ├── access.log
    │   └── error.log
    └── certbot-renew.log

二十一、一键启动命令汇总

cd /opt/private-cloudflare

docker compose up -d

docker compose ps

docker compose logs -f nginx

重载 Nginx:

docker compose exec nginx nginx -s reload

停止服务:

docker compose down

更新镜像:

docker compose pull
docker compose up -d

总结

Cloudflare 本身无法完整私有化部署,但我们可以通过 Nginx、ModSecurity、OWASP CRS、Certbot、WireGuard、CrowdSec 等开源组件,自建一套具备反向代理、HTTPS、WAF、访问控制、限流、日志审计和内网穿透能力的私有边缘网关。

这套方案适合企业内部系统、个人实验室、多云混合部署、内网服务安全暴露等场景。它的核心价值在于:把公网入口收敛到自有网关,将安全能力前置,并通过配置文件统一管理访问策略

如果你的业务对全球访问加速和大规模 DDoS 防护要求很高,仍然建议使用 Cloudflare、AWS CloudFront、Akamai、Fastly 等专业 CDN 和安全厂商;如果你的重点是自主可控、私有化、安全访问和成本优化,那么本文方案是一个非常实用的落地选择。

目录结构
全文