通过动态生成 nginx 配置的方式来实现 IP 白名单。
本项目是 whitelist(C#) 使用 rust 重写的版本,功能完全相同,配置文件不兼容,相信会比 C# 版更加稳定和节省资源。
(当然这依然是个练手项目,也是我第一次写 rust 项目)
配置文件的搜索顺序:
- 环境变量
APP_CONFIG
指定的配置文件,需要包含文件名的完整路径 - 当前工作目录下的
config.json
- exe 同级目录下的
config.json
必要的配置(config.json):
{
"listen": {
"urls": [
"127.0.0.1:8080",
"[::1]:8080"
],
"path": "/a"
},
"whitelist": {
"token": "aaa",
"nginx_conf": "Z:\\whitelist.conf",
"nginx_exe": "D:\\scoop\\home\\apps\\nginx\\current\\nginx.exe"
}
}
完整配置(config.full.json):
{
"listen": {
"urls": [
"127.0.0.1:8080",
"[::1]:8080"
],
"path": "/a",
"allow_proxy": true
},
"whitelist": {
"token": "aaa",
"nginx_conf": "Z:\\whitelist.conf",
"nginx_exe": "D:\\scoop\\home\\apps\\nginx\\current\\nginx.exe",
"remote_addr_var": "my_real_ip",
"result_var": "ip_whitelist",
"timeout": 3600,
"loop_delay": 15,
"ipv4_prefixlen": 0,
"ipv6_prefixlen": 0,
"preset": [
"127.0.0.0/8",
"192.168.1.1"
]
},
"message": {
"bark": ""
},
"baidu_location": {
"ak": "",
"referrer": ""
}
}
说明:
allow_proxy
:是否开启代理支持,开启后将从相关 http 头中获取远程地址,默认为true
remote_addr_var
:nginx 配置文件中表示远程地址的变量名,默认为remote_addr
result_var
:nginx 配置文件中保存结果的变量名,默认为ip_whitelist
,如果remote_addr
在白名单中,该变量值为1
timeout
:成功提交后保留多久,单位为秒,默认3600
loop_delay
:多久检查一次列表,为了避免频繁重载 nginx 配置,提交成功和过期都不是实时的,默认为15
ipv4_prefixlen
:成功提交后,把该范围内的 IP 都加入白名单,默认为0
,等同于32
ipv6_prefixlen
:同上preset
:预置的白名单,始终会包含这些 IP 或 IP 段bark
:消息通知接口,不含最后的/
ak
:百度地图 API,用于获取 IP 的地理位置,仅在设置了bark
、发送消息时使用referrer
:调用百度地图 API 时的 referrer,参见百度地图 API 文档的来源白名单
使用 rust 的 env_logger 库管理日志,所以需要通过环境变量来设置日志。
$ export RUST_LOG=info,whitelist_rs=debug
$ ./whitelist_rs
这将设置默认日志级别为 info,当前程序的日志级别为 debug。
- 修改
whitelist_rs.service
文件中的相关路径 - 运行
up.sh
安装服务并开启 - 运行
log.sh
查看日志
server {
location = /a {
proxy_redirect off;
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
在需要白名单的地方:
include whitelist.conf;
server {
location = /xxx {
if ($ip_whitelist != 1) {
return 403;
}
}
}
- 手动访问
http://.../a
,在页面中填写 token - 或者,直接向
http://.../a
发送 POST 请求,参数为token=xxx
- 成功会看到
hello
,最多 15 秒后白名单即可生效 - 成功一次将保持 1 小时,超时后会自动清除,需要再次提交
- 强烈建议使用 https
- 对于爆破,日志中会输出相关信息,可以配合使用 fail2ban 自动拉黑 IP