Nginx 全局拦截所有域名访问 .git 目录(踩坑记录)

20次阅读
没有评论

前言

很多人想给 Nginx 做统一防护,禁止网站暴露 .git 源码目录,初衷是想直接在 http {} 块写 location 规则实现全局拦截。 这里有一个高频坑:location 指令不能直接写在 http{} 顶层,配置会直接报错,提示 [emerg] "location" directive is not allowed here。

本文提供 3 套可行方案,实现所有域名统一拦截 .git,按需选用。

安全提醒:禁止访问只是防护手段,最根本的做法是不要把 .git 目录部署到线上服务器。


方案一:snippets 片段引入(推荐,生产最佳实践)

思路:把拦截规则单独抽成一个配置片段,每个 server 只需要一行 include 引入,新增站点自动复用,便于统一管理。

1. 创建拦截规则文件

路径示例:/etc/nginx/snippets/block_git.conf

# 拦截 .git 目录下所有资源,例如 /.git/config、/.git/HEAD
location ~ /\.git {
    return 403;
}

# 额外拦截敏感文件:.gitignore .gitmodules .env .svn
location ~ /\.(gitignore|gitmodules|env|svn) {
    return 403;
}

2. 在每个虚拟主机 server {} 内引入片段

server {
    listen 80;
    server_name demo1.com;

    # 引入全局拦截规则
    include snippets/block_git.conf;

    root /data/www/demo1;
    location / {
        try_files $uri $uri/ /index.html;
    }
}

server {
    listen 80;
    server_name demo2.com;
    # 第二个域名同样一行引入,无需重复写规则
    include snippets/block_git.conf;

    root /data/www/demo2;
}

✅ 优点:

  • 统一管理,修改一次,所有站点生效
  • 无性能坑,location 是 Nginx 原生匹配方式,稳定可靠
  • 符合 Nginx 官方规范

方案二:http 块使用 if + $request_uri 全局拦截(无需每个 server 引入)

适用场景:不想改动每一个 server 配置,直接在 http{} 写全局规则,所有域名自动生效。

直接写在 nginx.conf 的 http {} 内部:

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

    # 全局拦截 URI 包含 /.git 的请求,所有域名生效
    if ($request_uri ~* "/\.git") {
        return 403;
    }

    # 原有其他配置
    sendfile        on;
    keepalive_timeout  65;

    server {
        # ...你的站点配置
    }
}

说明:~* 代表不区分大小写匹配;if 在 http 块是合法语法。

⚠️ 注意:if 属于 Nginx 内置变量判断,性能略低于 location,访问量巨大的站点优先选方案一。


方案三:单站点直接写在 server 块(简单测试场景)

少量站点可以直接在 server 内部写规则,适合服务器域名很少的场景:

server {
    listen 80;
    server_name demo.com;

    location ~ /\.git {
        return 403;
    }

    root /data/www/demo;
    location / {
        try_files $uri $uri/ /index.html;
    }
}

配置校验 & 重载

每次修改配置,务必先检查语法,再重载,避免服务挂掉:

# 检查配置语法
nginx -t

# 平滑重载配置,不中断业务
nginx -s reload

测试验证

使用 curl 测试访问 .git/config:

curl -I http://demo.com/.git/config

正常返回 403 Forbidden 即拦截生效。

可选:如果你想伪装成文件不存在,把 return 403; 修改为 return 404;

常见踩坑总结

  1. ❌ 错误写法:http {} 里面直接写 location,Nginx 启动报错,location 只能放在 server 或 location 内部。
  2. 正则匹配 \.git:反斜杠转义 .,防止匹配到普通单词 git。
  3. 防护优先级:物理删除服务器上的 .git 目录 > Nginx 拦截。Nginx 只是访问层防护,不能替代源码目录清理。

扩展

可以在同一条规则增加更多敏感目录拦截,例如 .svn、.env、.htaccess,防止源码、配置文件泄露。

正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 0
评论(没有评论)
验证码