Nginx+GeoIP2+防盗链+防爬虫+限制访问速度+限制连接数

最近看到群里有人问自己的业务被境外IP给撸了,能不能直接拦截境外的IP,只允许境内访问,刚好有群友说了句可以用GeoIP2,于是我就实践了一下,确实可以!
环境

1、CentOS7.9
2、Nginx1.22
3、GeoIP2模块
4、MaxMind国家IP库
5、libmaxminddb工具(用于解析MaxMind国家IP库文件)

官方下载链接:

CentOS7.9:http://isoredirect.centos.org/centos/7/isos/x86_64/
Nginx:https://nginx.org/download/nginx-1.22.1.tar.gz
GeoIP2模块:https://github.com/leev/ngx_http_geoip2_module/releases
MaxMind国家IP库: https://www.maxmind.com/en/home
libmaxminddb工具:https://github.com/maxmind/libmaxminddb/releases

一、编译安装libmaxminddb
1
2
3
4
5
这里下的是1.7.1版本
tar -zxvf libmaxminddb-1.7.1.tar.gz
cd libmaxminddb-1.7.1
make && make check && make install
ldconfig
二、解压GeoIP2
1
2
3
因为使用的是Nginx1.22的版本,所以GeoIP2只能用3.3版本的,不然会报错
tar -zxvf ngx_http_geoip2_module-3.3.tar.gz
mv ngx_http_geoip2_module-3.3 /usr/local/
三、编译安装Nginx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
tar -zxvf nginx-1.22.1.tar.gz
cd nginx-1.22.1

./configure --prefix=/usr/local/nginx \
--with-http_realip_module \
--with-http_sub_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-http_v2_module \
--with-stream \
--with-openssl=/usr/local/openssl/ \
--with-pcre=/usr/local/pcre-8.32/ \
--with-zlib=/usr/local/zlib-1.2.13/ \
--add-module=/usr/local/ngx_http_geoip2_module-3.3
四、注册MaxMind帐号并下载国家IP数据库

注册
下载数据库1
下载数据库2

五、将下载的数据库解压并放到指定位置

这个位置并不一定说是要在哪里,只要到时候你Nginx调用的时候路径是对的就行

1
2
3
4
mkdir -p /usr/local/nginx/IPData/
tar -zxvf GeoLite2-Country_20230726.tar.gz
cd GeoLite2-Country_20230726
mv GeoLite2-Country.mmdb /usr/local/nginx/IPData/

六、配置Nginx实现禁止境外IP访问、防盗链、防爬虫、限制访问速度、限制连接数
1
2
mkdir -p /usr/local/nginx/conf/v_host/
vim /usr/local/nginx/conf/nginx.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

#两个Nginx线程
worker_processes 2;

events {
#每个线程可以处理1024个连接请求
worker_connections 1024;
}


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

server_tokens off; #关闭Nginx版本号
proxy_buffering off;
sendfile on;
keepalive_timeout 20;
keepalive_requests 200;

#配置国家IP库
geoip2 /usr/local/nginx/IPData/GeoLite2-Country.mmdb{
auto_reload 5m;
$geoip2_metadate_country_build metadata build_epoch;
$geoip2_data_country_code country iso_code;
$geoip2_country_name country names en;
}

#配置规则,默认不允许所有IP访问,只允许中国IP访问
map $geoip2_data_country_code $allowed_country {
default no;
CN yes;
}


#设置白名单,在下列白名单中不限速
geo $is_whitelist {
default 0;
192.168.0.0/24 1;
}
map $is_whitelist $limit_key {
1 "";
0 $binary_remote_addr;
}
#设置连接数
limit_conn_zone $binary_remote_addr zone=perip:10m;
#设置限制连接数,每秒150个连接数
limit_req_zone $binary_remote_addr zone=myRateLimit:10m rate=150r/s;
#设置限制连接数,每秒2000个连接数
limit_req_zone $binary_remote_addr zone=mywebRateLimit:10m rate=2000r/s;
#设置限制连接数,每秒200个连接数
limit_req_zone $binary_remote_addr zone=my26051RateLimit:10m rate=200r/s;

引用v_host中的指定conf配置文件
include /usr/local/nginx/conf/v_host/website.conf;
}
1
vim /usr/local/nginx/conf/v_host/website.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#HTTP配置

server {
listen 80;
charset utf-8;
server_name website.abc.com;
client_max_body_size 300m;
access_log /usr/local/nginx/logs/websitehttp_access.log;
error_log /usr/local/nginx/logs/websitehttp_error.log debug;

#当访问http时,强制跳转到https
error_page 497 https://website.abc.com$uri?$args;

#添加客户端的IP头
add_header client-country $geoip2_data_country_code;

#启用压缩,压缩等级为9级,压缩text/css text/plan text/xml application/javascript
#application/x-javascript application/html application/xml image/png image/jpg
#image/jpeg image/gif image/webp image/svg+xml 这些格式的文件
gzip on;
gzip_comp_level 9;
gzip_types text/css text/plan text/xml application/javascript application/x-javascript application/html application/xml image/png image/jpg image/jpeg image/gif image/webp image/svg+xml;

#做判断,如果国家不是中国,就返回451状态码给客户端;
if ($geoip2_data_country_code != CN ) {
return 451;
}

#做判断,如果匹配到默认不允许的规则,就返回451状态码给客户端;
if ($geoip2_data_country_code = no ) {
return 451;
}

location /{
root /www/website/;
index index.html;
try_files $uri $uri/ /index.html?s=$uri&$args;

#限制连接数为nginx.conf配置的zone=myRateLimit的值(每秒150个请求数),允许突然爆发的连接数10个并且是马上执行没有延迟
limit_req zone=myRateLimit burst=10 nodelay;

#限制每个IP每秒连接数为nginx.conf配置的zone=perip的值(单个IP允许150个请求数)
limit_conn perip 150;

#如果超过设定的每秒150个连接数这个阈值,则返回448状态码给客户端
limit_req_status 448;

#如果超过设定的每个IP每秒150个连接数这个阈值,则返回449状态码给客户端
limit_conn_status 449;

#限制客户端速度只能到150k
limit_rate 150k;

#防盗链,如果请求的头不是website.abc.com就是无效的,则返回449状态码给客户端
valid_referers none blocked website.abc.com;
if ($invalid_referer) {
return 449;
}

#做判断,如果国家不是中国,就返回451状态码给客户端;
if ($geoip2_data_country_code != CN ) {
return 451;
}

#做判断,如果匹配到默认不允许的规则,就返回451状态码给客户端
if ($geoip2_data_country_code = no ) {
return 451;
}

#防爬虫,如果UA是底下任意一个值,就判定为蜘蛛爬虫,则返回451给客户端
if ($http_user_agent ~* "python|curl|java|wget|httpclient|okhttp|qihoobot|Scrubby|YodaoBot|yahoo-blogs/v3.9|Gigabot|yahoo-mmcrawler|Teoma|Robozilla|Bingbot|Slurp|Baiduspider|Googlebot|googlebot-mobile|googlebot-image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo!Slurp|Yahoo!Slurp China|YoudaoBot|Sosospider|MSNBot|ia_archiver|twiceler|psbot") {
return 451;
}

}

#错误页配置,如果状态码是下列的值,就显示我配置的页面
error_page 400 401 402 403 404 500 502 503 504 /error.html;

location = /error.html {
root /usr/local/html;

#限制连接数为nginx.conf配置的zone=myRateLimit的值(每秒150个请求数),允许突然爆发的连接数10个并且是马上执行没有延迟
limit_req zone=myRateLimit burst=10 nodelay;

#限制每个IP每秒连接数为nginx.conf配置的zone=perip的值(单个IP允许150个请求数)
limit_conn perip 150;

#如果超过设定的每秒150个连接数这个阈值,则返回448状态码给客户端
limit_req_status 448;

#如果超过设定的每个IP每秒150个连接数这个阈值,则返回449状态码给客户端
limit_conn_status 449;

#限制客户端速度只能到150k
limit_rate 150k;

#防盗链,如果请求的头不是website.abc.com就是无效的,则返回449状态码给客户端
valid_referers none blocked website.abc.com;
if ($invalid_referer) {
return 449;
}

#做判断,如果国家不是中国,就返回451状态码给客户端;
if ($geoip2_data_country_code != CN ) {
return 451;
}

#做判断,如果匹配到默认不允许的规则,就返回451状态码给客户端
if ($geoip2_data_country_code = no ) {
return 451;
}

#防爬虫,如果UA是底下任意一个值,就判定为蜘蛛爬虫,则返回451给客户端
if ($http_user_agent ~* "python|curl|java|wget|httpclient|okhttp|qihoobot|Scrubby|YodaoBot|yahoo-blogs/v3.9|Gigabot|yahoo-mmcrawler|Teoma|Robozilla|Bingbot|Slurp|Baiduspider|Googlebot|googlebot-mobile|googlebot-image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo!Slurp|Yahoo!Slurp China|YoudaoBot|Sosospider|MSNBot|ia_archiver|twiceler|psbot") {
return 451;
}

}
}

#HTTPS配置

server {
listen 443 ssl;
charset utf-8;
server_name website.abc.com;
client_max_body_size 300m;
ssl_certificate /www/cert/website.abc.com.pem;
ssl_certificate_key /www/cert/website.abc.com.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
access_log /usr/local/nginx/logs/websitehttps_access.log;
error_log /usr/local/nginx/logs/websitehttps_error.log debug;

#添加客户端的IP头
add_header client-country $geoip2_data_country_code;

#启用压缩,压缩等级为9级,压缩text/css text/plan text/xml application/javascript
#application/x-javascript application/html application/xml image/png image/jpg
#image/jpeg image/gif image/webp image/svg+xml 这些格式的文件
gzip on;
gzip_comp_level 9;
gzip_types text/css text/plan text/xml application/javascript application/x-javascript application/html application/xml image/png image/jpg image/jpeg image/gif image/webp image/svg+xml;

#做判断,如果国家不是中国,就返回451状态码给客户端;
if ($geoip2_data_country_code != CN ) {
return 451;
}

#做判断,如果匹配到默认不允许的规则,就返回451状态码给客户端;
if ($geoip2_data_country_code = no ) {
return 451;
}

location /{
root /www/website/;
index index.html;
try_files $uri $uri/ /index.html?s=$uri&$args;

#限制连接数为nginx.conf配置的zone=myRateLimit的值(每秒150个请求数),允许突然爆发的连接数10个并且是马上执行没有延迟
limit_req zone=myRateLimit burst=10 nodelay;

#限制每个IP每秒连接数为nginx.conf配置的zone=perip的值(单个IP允许150个请求数)
limit_conn perip 150;

#如果超过设定的每秒150个连接数这个阈值,则返回448状态码给客户端
limit_req_status 448;

#如果超过设定的每个IP每秒150个连接数这个阈值,则返回449状态码给客户端
limit_conn_status 449;

#限制客户端速度只能到150k
limit_rate 150k;

#防盗链,如果请求的头不是website.abc.com就是无效的,则返回449状态码给客户端
valid_referers none blocked website.abc.com;
if ($invalid_referer) {
return 449;
}

#做判断,如果国家不是中国,就返回451状态码给客户端;
if ($geoip2_data_country_code != CN ) {
return 451;
}

#做判断,如果匹配到默认不允许的规则,就返回451状态码给客户端
if ($geoip2_data_country_code = no ) {
return 451;
}

#防爬虫,如果UA是底下任意一个值,就判定为蜘蛛爬虫,则返回451给客户端
if ($http_user_agent ~* "python|curl|java|wget|httpclient|okhttp|qihoobot|Scrubby|YodaoBot|yahoo-blogs/v3.9|Gigabot|yahoo-mmcrawler|Teoma|Robozilla|Bingbot|Slurp|Baiduspider|Googlebot|googlebot-mobile|googlebot-image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo!Slurp|Yahoo!Slurp China|YoudaoBot|Sosospider|MSNBot|ia_archiver|twiceler|psbot") {
return 451;
}

}

#错误页配置,如果状态码是下列的值,就显示我配置的页面
error_page 400 401 402 403 404 500 502 503 504 /error.html;

location = /error.html {
root /usr/local/html;

#限制连接数为nginx.conf配置的zone=myRateLimit的值(每秒150个请求数),允许突然爆发的连接数10个并且是马上执行没有延迟
limit_req zone=myRateLimit burst=10 nodelay;

#限制每个IP每秒连接数为nginx.conf配置的zone=perip的值(单个IP允许150个请求数)
limit_conn perip 150;

#如果超过设定的每秒150个连接数这个阈值,则返回448状态码给客户端
limit_req_status 448;

#如果超过设定的每个IP每秒150个连接数这个阈值,则返回449状态码给客户端
limit_conn_status 449;

#限制客户端速度只能到150k
limit_rate 150k;

#防盗链,如果请求的头不是website.abc.com就是无效的,则返回449状态码给客户端
valid_referers none blocked website.abc.com;
if ($invalid_referer) {
return 449;
}

#做判断,如果国家不是中国,就返回451状态码给客户端;
if ($geoip2_data_country_code != CN ) {
return 451;
}

#做判断,如果匹配到默认不允许的规则,就返回451状态码给客户端
if ($geoip2_data_country_code = no ) {
return 451;
}

#防爬虫,如果UA是底下任意一个值,就判定为蜘蛛爬虫,则返回451给客户端
if ($http_user_agent ~* "python|curl|java|wget|httpclient|okhttp|qihoobot|Scrubby|YodaoBot|yahoo-blogs/v3.9|Gigabot|yahoo-mmcrawler|Teoma|Robozilla|Bingbot|Slurp|Baiduspider|Googlebot|googlebot-mobile|googlebot-image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo!Slurp|Yahoo!Slurp China|YoudaoBot|Sosospider|MSNBot|ia_archiver|twiceler|psbot") {
return 451;
}

}
}
七、测试是否生效可用

使用境外IP访问测试

境外
451拦截

使用境内IP访问测试

境内
正常访问

基本上就配置完了并且是可以用的,爬虫啥的由于没有环境测试,有环境的话,可以试试!

戴戴的Linux

文章目录
  1. 1. 最近看到群里有人问自己的业务被境外IP给撸了,能不能直接拦截境外的IP,只允许境内访问,刚好有群友说了句可以用GeoIP2,于是我就实践了一下,确实可以!
    1. 1.1. 环境
    2. 1.2. 官方下载链接:
    3. 1.3. 一、编译安装libmaxminddb
    4. 1.4. 二、解压GeoIP2
    5. 1.5. 三、编译安装Nginx
    6. 1.6. 四、注册MaxMind帐号并下载国家IP数据库
    7. 1.7. 五、将下载的数据库解压并放到指定位置
    8. 1.8. 六、配置Nginx实现禁止境外IP访问、防盗链、防爬虫、限制访问速度、限制连接数
    9. 1.9. 七、测试是否生效可用
    10. 1.10. 基本上就配置完了并且是可以用的,爬虫啥的由于没有环境测试,有环境的话,可以试试!


本站总访问量 本文总阅读量