NGINX 配置内网访问
需求
我们有一个测试站的域名: https://test.zhiexa.com/ 这个域名是公网域名, 我希望限制其访问,只有在内网,或者办公室 IP 能够访问 ,该如何配置呢?
1. geo 模块配置
首先在虚拟主机文件中domain-vhost.conf
添加,全局模块
# 添加允许的IP地址
geo $allowed_ip {
default 0; # 默认拒绝所有IP
# 内网地址范围
10.0.0.0/8 1; # 允许所有10开头的内网IP
172.16.0.0/12 1; # 允许172.16-172.31范围的内网IP
192.168.0.0/16 1; # 允许所有192.168开头的内网IP
# 添加特定的外网IP(示例) xxx.xxx.xxx.137 改成自己希望可以访问的IP
xxx.xxx.xxx.137 1; # 允许特定的办公室IP
}
这部分使用 geo 模块创建了一个变量 $allowed_ip
,用于判断访问IP是否在允许列表中:
- 值为0表示禁止访问
- 值为1表示允许访问
2. 访问控制判断
在server 段里面配置
# 在server 段配置
if ($allowed_ip = 0) {
return 403; # 如果IP不在允许列表中,返回403禁止访问错误
}
3. 错误页面配置
在server 段里面配置
# 先配置错误页面,将403错误重定向到一个命名location
error_page 403 @403_handler;
# 使用命名location来处理403错误
location @403_handler {
root /usr/local/nginx/html;
try_files /403.html =404;
# 强制添加调试头信息 可以不用添加,调试使用
add_header X-Debug-Path $document_root always;
add_header X-Debug-File $request_filename always;
add_header X-Debug-Uri $uri always;
add_header X-Debug-Request-Uri $request_uri always;
add_header X-Debug-Remote-Addr $remote_addr always;
# 确保内容类型正确
default_type text/html;
charset utf-8;
# 详细的错误日志
error_log /usr/local/nginx/logs/403_debug.log debug;
}
# 正确配置错误页面 403.html 放在这个位置 /usr/local/nginx/html/403.html
location = /403.html {
root /usr/local/nginx/html;
internal; # 只允许内部重定向访问,不能直接从外部访问
}
-
error_page 403 @403_handler 将403错误重定向到一个命名location
-
location @403_handler 定义了处理403错误的具体方式,包括显示自定义错误页面和添加调试信息
-
location = /403.html 定义了403错误页面的位置,并设置为internal,防止直接访问
整个配置的工作流程是:
- 当有请求访问服务器时,Nginx检查访问IP
- 通过geo模块判断IP是否在允许列表中
- 如果不在允许列表中,返回403错误
- 403错误被重定向到自定义错误页面
- 同时记录详细的调试信息和日志
- 这样就实现了只允许特定IP访问,其他IP都会被拒绝并显示自定义错误页面的功能。
我需要准备一个 403.html
页面 , 这个页面放到 /usr/local/nginx/html
这个目录下面
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>访问被拒绝 - 智AI</title>
<style>
body {
font-family: 'PingFang SC', 'Helvetica Neue', Arial, sans-serif;
background-color: #f8f9fa;
color: #333;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
padding: 0 20px;
}
.container {
max-width: 600px;
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
padding: 40px;
text-align: center;
}
.icon {
font-size: 64px;
margin-bottom: 20px;
color: #f44336;
}
h1 {
font-size: 28px;
margin-bottom: 20px;
color: #333;
}
p {
font-size: 16px;
line-height: 1.6;
color: #666;
margin-bottom: 30px;
}
.btn {
display: inline-block;
background-color: #1890ff;
color: white;
text-decoration: none;
padding: 10px 20px;
border-radius: 4px;
font-size: 16px;
transition: background-color 0.3s;
}
.btn:hover {
background-color: #40a9ff;
}
</style>
</head>
<body>
<div class="container">
<div class="icon">🚫</div>
<h1>访问被拒绝</h1>
<p>很抱歉,您当前的IP地址没有权限访问此页面。此页面仅限内部网络或授权IP访问。</p>
<p>如需访问,请使用公司网络或联系管理员将您的IP添加到白名单。</p>
<!-- 换成 公网正式域名 -->
<a href="https://blog.youkuaiyun.com/u010339879" class="btn">前往公开网站</a>
</div>
</body>
</html>
4. 一个完整的配置
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# 添加允许的IP地址
geo $allowed_ip {
default 0;
# 内网地址范围
10.0.0.0/8 1; # 10.0.0.0 - 10.255.255.255
172.16.0.0/12 1; # 172.16.0.0 - 172.31.255.255
192.168.0.0/16 1; # 192.168.0.0 - 192.168.255.255
# 添加特定的外网IP(示例)
222.65.141.137 1; # office ip
47.116.213.148 1; # 测试服务器IPIP_ADDRESS 1;
}
server {
listen 80;
server_name test.zhiexa.com;
# 添加访问日志以便调试
access_log /usr/local/nginx/logs/test.com.access.log main;
error_log /usr/local/nginx/logs/test.com.error.log debug;
# 重定向到https
return 302 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name test.zhiexa.com;
# 添加访问日志以便调试
access_log /usr/local/nginx/logs/test.com.ssl.access.log main buffer=16k flush=5s;
error_log /usr/local/nginx/logs/test.com.ssl.error.log debug;
# 先配置错误页面
error_page 403 @403_handler;
# 使用命名location来处理403错误
location @403_handler {
root /usr/local/nginx/html;
try_files /403.html =404;
# 强制添加调试头信息
add_header X-Debug-Path $document_root always;
add_header X-Debug-File $request_filename always;
add_header X-Debug-Uri $uri always;
add_header X-Debug-Request-Uri $request_uri always;
add_header X-Debug-Remote-Addr $remote_addr always;
# 确保内容类型正确
default_type text/html;
charset utf-8;
# 详细的错误日志
error_log /usr/local/nginx/logs/403_debug.log debug;
}
if ($allowed_ip = 0) {
return 403;
}
# 正确配置错误页面
location = /403.html {
root /usr/local/nginx/html;
internal;
}
ssl_certificate cert/zhiexa.com.pem;
ssl_certificate_key cert/zhiexa.com.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
# 开启 Gzip 压缩
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# 根路径配置
location / {
root /aaa/zhiexa-cloud-web/dist/;
try_files $uri $uri/ /index.html;
index index.html;
error_log /usr/local/nginx/logs/test.com.root.error.log debug;
# HTML 文件缓存控制
location ~* \.(html|htm)$ {
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
expires off;
# add_header X-Debug-Path $document_root always;
# add_header X-Debug-Uri $uri always;
}
# 设置 .css 和 .js 文件的缓存时间为 4 小时
location ~* \.(css|js)$ {
expires 4h;
add_header Cache-Control "public, no-transform";
}
# 设置图片文件的缓存时间为 4 小时
location ~* \.(gif|jpg|jpeg|png|svg)$ {
expires 4h;
add_header Cache-Control "public, no-transform";
}
}
location /h5 {
root /service/customized-h5;
try_files $uri $uri/ /index.html;
index index.html;
# 禁用 HTML 文件的缓存
location ~* \.(html|htm)$ {
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
expires off;
}
# 设置 .css 和 .js 文件的缓存时间为 4 小时
location ~* \.(css|js)$ {
expires 4h;
add_header Cache-Control "public, no-transform";
}
# 设置图片文件的缓存时间为 4 小时
location ~* \.(gif|jpg|jpeg|png|svg)$ {
expires 4h;
add_header Cache-Control "public, no-transform";
}
}
location /api/file-assistant {
# 真实代理的IP:PORT
proxy_pass http://172.xxx.xxxx.xxx:8200;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 300; #代理连接web超时时间
proxy_send_timeout 600; #web回传数据至代理超时时间
proxy_read_timeout 600; #代理等待web响应超时时间
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_cache off;
proxy_buffering off;
}
location /zhiexa/prompt/api/v1 {
# 真实代理的IP:PORT
proxy_pass http://172.xxx.xxxx.xxx:8009/zhiexa/prompt/api/v1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 300; #代理连接web超时时间
proxy_send_timeout 300; #web回传数据至代理超时时间
proxy_read_timeout 300; #代理等待web响应超时时间
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_buffering on; #开启代理缓冲区,web回传数据至缓冲区,代理边收边传给客服端
proxy_buffer_size 32k; #代理接收web响应的头部信息的缓冲区大小
proxy_buffers 4 128k; # 缓冲代理接收单个长连接内包含的web相应的数量和大小
}
}
配置完成后 重启 NGINX ,或者重新加载配置文件即可 。
# 检查配置文件 是否存在语法错误
nginx -t
# 重新加载配置文件
nginx -s reload
参考文档
Nginx 官方文档 ngx_http_geo_module