├── .DS_Store
├── .idea
├── .gitignore
├── DK8sDDosFirewall.iml
├── modules.xml
└── vcs.xml
├── Dockerfile
├── DockerfileTest
├── LICENSE
├── Makefile
├── README.md
├── cert.key
├── cert.pem
├── env.conf
├── forward.sh
├── nginx.conf
├── protect.lua
├── record.lua
├── stats.lua
├── wechat.jpg
└── wrk.lua
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yinyue123/DK8sDDosFirewall/e55de6074a1f2906d2826f93bd6ca7e3de2ab18c/.DS_Store
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/DK8sDDosFirewall.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openresty/openresty:1.21.4.2-alpine as builder
2 | RUN mkdir /app
3 | WORKDIR /app
4 |
5 | ADD stats.lua /app
6 | ADD protect.lua /app
7 | ADD record.lua /app
8 |
9 | RUN /usr/local/openresty/luajit/bin/luajit -b /app/stats.lua /app/stats.ljbc
10 | RUN /usr/local/openresty/luajit/bin/luajit -b /app/protect.lua /app/protect.ljbc
11 | RUN /usr/local/openresty/luajit/bin/luajit -b /app/record.lua /app/record.ljbc
12 |
13 | FROM --platform=linux/amd64 openresty/openresty:1.21.4.2-alpine
14 | EXPOSE 80 443 3000
15 |
16 | RUN mkdir /app
17 | WORKDIR /app
18 | RUN apk add --no-cache tzdata
19 | ENV TZ Asia/Shanghai
20 | COPY --from=builder /app/stats.ljbc /app/
21 | COPY --from=builder /app/protect.ljbc /app/
22 | COPY --from=builder /app/record.ljbc /app/
23 | ADD stats.lua /app/stats.lua
24 | ADD protect.lua /app/protect.lua
25 | ADD record.lua /app/record.lua
26 | ADD cert.key /app/cert.key
27 | ADD cert.pem /app/cert.pem
28 | ADD env.conf /app/env.conf
29 | ADD nginx.conf /app/nginx.conf
30 |
31 | CMD ["openresty", "-c", "/app/nginx.conf"]
32 |
--------------------------------------------------------------------------------
/DockerfileTest:
--------------------------------------------------------------------------------
1 | FROM --platform=linux/amd64 centos:7
2 | EXPOSE 80 443 3000
3 | RUN mkdir /app
4 | WORKDIR /app
5 |
6 | RUN yum install -y yum-utils
7 | RUN yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo && yum install -y openresty openresty-resty openresty-opm
8 | RUN yum install -y vim
9 |
10 | ADD stats.lua /app/stats.lua
11 | ADD protect.lua /app/protect.lua
12 | ADD ping.lua /app/ping.lua
13 | ADD record.lua /app/record.lua
14 | ADD cert.key /app/cert.key
15 | ADD cert.pem /app/cert.pem
16 | ADD env.conf /app/env.conf
17 | ADD nginx.conf /app/nginx.conf
18 |
19 | CMD ["openresty", "-c", "/app/nginx.conf"]
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | PROD_REG?=yinyue123/ddos-firewal
2 | IMG_TAG?=v2.4
3 | PROD_IMG?=${PROD_REG}:${IMG_TAG}
4 | export DOCKER_HOST?=tcp://192.168.10.1:2375
5 |
6 | all: push
7 |
8 | push:
9 | docker build -f Dockerfile . -t $(PROD_IMG)
10 | docker push ${PROD_IMG}
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DK8sDDosFirewall
2 | Protect your service from CC attacks, UDP attacks, and traffic flooding attacks.
3 |
4 | [DK8s DDos Firewall Code Repository](https://github.com/yinyue123/DK8sDDosFirewall)
5 |
6 | [DK8s DDos Firewall Docker Image](https://hub.docker.com/r/yinyue123/ddos-firewal)
7 |
8 | `For more information, please visit `[https://www.dk8s.com](https://www.dk8s.com)
9 |
10 | 
11 |
--------------------------------------------------------------------------------
/cert.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIICXQIBAAKBgQCnbQUB9zZBiouSxLrl0VorHIPZswMdN64Sc39wBWy9J5Ze00cb
3 | y+IuH9lPYu688DlaAYande7tG2wuGSoBO4WzGSDnTKbd4YfmUZrWCmYvqqQsaEG/
4 | l+ml3Ap/m9KcrtCQUP3UMMfgcc20d3Zho07VfO86658he2u/qH3l3SU8DwIDAQAB
5 | AoGBAJ7U+QQ1X35sDh8tjVUK9+ygP6FehxzHvtb4RTSjoNYN4USSUQpYsHkrc8Ax
6 | TeVmTDJL8k+ZvRGpi0ZsTwIeUqXd41CbXqBtu59LuhsOQSYWhbTR4HU/cVueJbFD
7 | GKJ0x68mu9kQQcT2wpjLv4SeVFCIwQMudcL31U6CFtLbsR6JAkEA0SDAK9AxG/TM
8 | fW5jimmiaRte+ELqao8/rer/DGd6hEV2izb03HXRunQW4CuAIjiaILrmioRkgxya
9 | Mt8f5xaqNQJBAMzzgX5Al14H0h3BrzQSD3dmo0ims0guN7hIJQ+hhy4e9TLmZJwU
10 | 7oCjUTvdg2gbId9PEKkGmxFZ1pLtcXq6dbMCQEl044uAOX/EYP++AqDfsfiRcK5r
11 | csOzRX7liGjnABXuAFGuIBxAFkcT9+UN4pgioaDVhZ0qG9Qh+9fan+4f+/ECQFet
12 | 0Pc3IMqMY/pw8sg+9bjqAu7AyjAV/aZrztcaDl/PxKxK3j3bwpDrzYPj5ySxftMu
13 | 2vzEo7BPk7l1tTeA73sCQQCN05E0HTuDMhLbbNGfnKPoC6FChCI8QZgEMQ2MdkiT
14 | kGBaqi/AwtrCQBEDIV8yQrJpsHzXaCpBxCyZuj56m5Xh
15 | -----END RSA PRIVATE KEY-----
16 |
--------------------------------------------------------------------------------
/cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIICcTCCAdoCCQCi/HJ9vuqbgDANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJj
3 | bjELMAkGA1UECAwCc3oxCzAJBgNVBAcMAnhsMQ0wCwYDVQQKDARkazhzMQ0wCwYD
4 | VQQLDARkazhzMRUwEwYDVQQDDAx3d3cuZGs4cy5jb20xHzAdBgkqhkiG9w0BCQEW
5 | EDc5ODUyMzU5M0BxcS5jb20wHhcNMjMwNzI4MDkxOTEyWhcNMzMwNzI1MDkxOTEy
6 | WjB9MQswCQYDVQQGEwJjbjELMAkGA1UECAwCc3oxCzAJBgNVBAcMAnhsMQ0wCwYD
7 | VQQKDARkazhzMQ0wCwYDVQQLDARkazhzMRUwEwYDVQQDDAx3d3cuZGs4cy5jb20x
8 | HzAdBgkqhkiG9w0BCQEWEDc5ODUyMzU5M0BxcS5jb20wgZ8wDQYJKoZIhvcNAQEB
9 | BQADgY0AMIGJAoGBAKdtBQH3NkGKi5LEuuXRWiscg9mzAx03rhJzf3AFbL0nll7T
10 | RxvL4i4f2U9i7rzwOVoBhqd17u0bbC4ZKgE7hbMZIOdMpt3hh+ZRmtYKZi+qpCxo
11 | Qb+X6aXcCn+b0pyu0JBQ/dQwx+BxzbR3dmGjTtV87zrrnyF7a7+ofeXdJTwPAgMB
12 | AAEwDQYJKoZIhvcNAQELBQADgYEAUESQ4W5BRa9u2i+HbgPhZ3Rgv6LXKP5w91eC
13 | PFy2bRTY4dZcnxHtEWRfP4ulGrWCVA+eH2z6jA1H1iZ01YdZwU89h1ejQkfE80HY
14 | FCTAKhEotgBa4pu6w27VZXkwBeLAlE/N98BMzzdWkrLrDKUG9MSMmhLUns+ijlOz
15 | neFoPdM=
16 | -----END CERTIFICATE-----
17 |
--------------------------------------------------------------------------------
/env.conf:
--------------------------------------------------------------------------------
1 | set $limit_count_per_hour 3600;
2 | set $limit_bytes_per_hour 268435456;
3 | set $limit_costs_per_hour 3600;
4 | set $limit_count_per_day 10800;
5 | set $limit_bytes_per_day 1073741824;
6 | set $limit_costs_per_day 10800;
7 |
--------------------------------------------------------------------------------
/forward.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | forward_ip=${1:-'127.0.0.1'}
4 | echo "New Request forward to $forward_ip"
5 | iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to "$forward_ip:80"
6 | iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to "$forward_ip:443"
7 | iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
8 |
--------------------------------------------------------------------------------
/nginx.conf:
--------------------------------------------------------------------------------
1 | user root;
2 | daemon off;
3 | # 绑定cpu亲核性,减少cache未命中,请根据实际情况修改
4 | worker_processes 1;
5 | worker_cpu_affinity 1;
6 | # 日志输出到标准输出
7 | error_log /dev/stdout;
8 | events {
9 | # 设置单个worker连接数
10 | worker_connections 10240;
11 | use epoll;
12 | }
13 |
14 | http {
15 | # 配置名为access的log输出格式
16 | log_format access '$remote_addr $server_port - $http_host [$time_local] '
17 | '"$request" $status $body_bytes_sent '
18 | '"$http_referer" "$http_user_agent" '
19 | '$http_x_forwarded_for|$http_x_real_ip|$limit_key';
20 | # log日志输出到标准输出
21 | access_log /dev/stdout access;
22 | # 关闭日志,提高性能。开启日志,排查问题
23 | # access_log off;
24 |
25 | # 白名单不限速
26 | geo $limit {
27 | default 1;
28 | 192.168.0.0/24 0;
29 | 10.0.0.0/8 0;
30 | 127.0.0.0/8 0;
31 | }
32 |
33 | # Header有X-Forwarded-IP就用xff,没有就用数据包的源IP
34 | map $http_x_forwarded_for $real_ip {
35 | default $remote_addr;
36 | "~^(?P[^,]+)" $ip;
37 | }
38 |
39 | # 匹配到白名单就为空不限速,没匹配到就限速
40 | map $limit $limit_key {
41 | 0 "";
42 | 1 $real_ip;
43 | }
44 |
45 | geo $whitelist {
46 | default 0;
47 | 1.1.1.1/24 1; # cdn的ip访问白名单
48 | }
49 |
50 | # 请求超过阈值,断开连接
51 | limit_req_status 444;
52 | # 限制单个ip的请求数,避免单个ip打爆服务,请根据实际业务进行修改
53 | limit_req_zone $limit_key zone=req_ip:10m rate=5r/s;
54 | # 限制单个服务的请求数,避免请求过载打爆服务,请根据实际业务进行修改
55 | limit_req_zone $server_name zone=req_svr:1m rate=1000r/s;
56 | # 限制单个uri的请求数,避免带宽被打爆,请根据实际业务进行修改
57 | limit_req_zone $uri zone=req_res:10m rate=3r/s;
58 | # 连接数超过阈值,断开连接
59 | limit_conn_status 444;
60 | # 限制单个ip的连接数
61 | limit_conn_zone $limit_key zone=con_ip:10m;
62 | # 限速的共享内存,如果不够可以改大
63 | lua_shared_dict traffic_stats 50m;
64 | # 引入lua模块
65 | lua_package_path "/app/?.ljbc;/app/?.lua;;";
66 | server {
67 | # 设置dns解析
68 | resolver 8.8.8.8 ipv6=off;
69 | # 监听80和443端口
70 | listen 80;
71 | listen 443 ssl;
72 | # 关闭文件索引,避免文件结构泄漏
73 | autoindex off;
74 | # 设置静态文件的目录
75 | root /www;
76 | # 开启OCSP装订,加速TLS握手效率
77 | ssl_stapling on;
78 | ssl_stapling_verify on;
79 | # 配置ssl证书和密钥
80 | ssl_certificate /app/cert.pem;
81 | ssl_certificate_key /app/cert.key;
82 | # SSL会话有效期
83 | ssl_session_timeout 5m;
84 | # 使用SSL版本,加密算法
85 | ssl_protocols TLSv1.2 TLSv1.3;
86 | ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
87 | ssl_prefer_server_ciphers on;
88 | # 开启HSTS,强制用户浏览器使用https协议
89 | add_header Strict-Transport-Security "max-age=2592000";
90 |
91 | # 开启gzip压缩,配置压缩文件类型,压缩等级,最小压缩长度,关闭IE浏览器压缩
92 | gzip on;
93 | gzip_types *;
94 | gzip_comp_level 6;
95 | gzip_min_length 256;
96 | gzip_buffers 16 8k;
97 | gzip_proxied any;
98 | gzip_vary on;
99 | gzip_disable "MSIE [1-6]\.(?!.*SV1)";
100 |
101 | # 配置匹配的域名 (重要,必须修改)
102 | server_name www.dk8s.com;
103 |
104 | # 限制下行带宽
105 | limit_rate 100k;
106 | limit_rate_after 1m;
107 |
108 | # 限制连接数
109 | limit_conn con_ip 40;
110 |
111 | # 检查客户浏览器端是否断开连接
112 | lua_check_client_abort on;
113 |
114 | # 引入限速配置文件
115 | include /app/env.conf;
116 |
117 | # 开启CDN源IP访问白名单
118 | # deny all;
119 | # allow $whitelist;
120 |
121 | # 如果后段服务为http服务,请保留这一段,并修改后段服务地址
122 | location / {
123 | # 对单个ip进行限速,请根据实际业务进行修改
124 | limit_req zone=req_ip burst=100 delay=200;
125 | # 对整个服务进行限速,请根据实际业务进行修改
126 | limit_req zone=req_svr burst=1000 delay=2000;
127 | # 向后端传递host名
128 | proxy_set_header Host $host;
129 | # 对请求IP进行限速处理
130 | access_by_lua_file /app/protect.ljbc;
131 | # 对请求IP流量进行统计
132 | log_by_lua_file /app/record.ljbc;
133 | # 调试使用
134 | # lua_code_cache off;
135 | # access_by_lua_file /app/protect.lua;
136 | # log_by_lua_file /app/record.lua;
137 | # 如果是纯静态网站,请保留index,并删除proxy_pass。
138 | # index index.php index.html index.htm;
139 | # 后段服务地址,请 根据实际情况修改
140 | proxy_pass http://127.0.0.1:3000;
141 | }
142 |
143 | # 后段服务为php-fpm。请保留这一段,否则删除
144 | # location / {
145 | # # 对单个ip进行限速,请根据实际业务进行修改
146 | # limit_req zone=req_ip burst=100 delay=200;
147 | # # 对整个服务进行限速,请根据实际业务进行修改
148 | # limit_req zone=req_svr burst=1000 delay=2000;
149 | # # 向后端传递host名
150 | # proxy_set_header Host $host;
151 | # # 对请求IP进行限速处理
152 | # access_by_lua_file /app/protect.ljbc;
153 | # # 对请求IP流量进行统计
154 | # log_by_lua_file /app/record.ljbc;
155 | # # 调试使用
156 | # # lua_code_cache off;
157 | # # access_by_lua_file /app/protect.lua;
158 | # # log_by_lua_file /app/record.lua;
159 | # # 逐个匹配php、html、htm
160 | # index index.php index.html index.htm;
161 | # }
162 |
163 | # 后段服务为php-fpm。请保留这一段,否则删除
164 | # location ~ \.php$ {
165 | # # 对单个ip进行限速,请根据实际业务进行修改
166 | # limit_req zone=req_ip burst=100 delay=200;
167 | # # 对整个服务进行限速,请根据实际业务进行修改
168 | # limit_req zone=req_svr burst=1000 delay=2000;
169 | # # 向后端传递host名
170 | # proxy_set_header Host $host;
171 | # # 对请求IP进行限速处理
172 | # access_by_lua_file /app/protect.ljbc;
173 | # # 对请求IP流量进行统计
174 | # log_by_lua_file /app/record.ljbc;
175 | # # 调试使用
176 | # # lua_code_cache off;
177 | # # access_by_lua_file /app/protect.lua;
178 | # # log_by_lua_file /app/record.lua;
179 | # # php-fpm的地址,请 根据实际情况修改
180 | # fastcgi_pass 127.0.0.1:9000;
181 | # fastcgi_index index.php;
182 | # fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
183 | # include fastcgi_params;
184 | # }
185 |
186 | # 查看ip的统计信息
187 | location /dk8s.stats {
188 | # 对单个ip进行限速
189 | limit_req zone=req_ip burst=100 delay=200;
190 | # 对整个服务进行限速
191 | limit_req zone=req_svr burst=1000 delay=2000;
192 | # lua_code_cache off;
193 | # access_by_lua_file /app/protect.lua;
194 | # log_by_lua_file /app/record.lua;
195 | access_by_lua_file /app/protect.ljbc;
196 | content_by_lua_file /app/stats.ljbc;
197 | log_by_lua_file /app/record.ljbc;
198 | }
199 |
200 | # 图片资源等信息,用作配置浏览器缓存。请修改后段服务地址,或删除proxy_pass,并把图片存到/www/所在位置
201 | location ~* \.(jpg|png|jpeg)$ {
202 | # 对单个ip进行限速
203 | limit_req zone=req_ip burst=100 delay=200;
204 | # 对整个服务进行限速
205 | limit_req zone=req_svr burst=1000 delay=2000;
206 | # 对uri进行限速,防止刷单个资源,导致带宽被打爆
207 | limit_req zone=req_res burst=200 delay=1000;
208 | # lua_code_cache off;
209 | # access_by_lua_file /app/protect.lua;
210 | # log_by_lua_file /app/record.lua;
211 | # 设置浏览器资源过期时间
212 | expires 7d;
213 | proxy_set_header Host $host;
214 | access_by_lua_file /app/protect.ljbc;
215 | log_by_lua_file /app/record.ljbc;
216 | # 后段服务地址,请 根据实际情况修改。如果资源存在/www/所在的位置,请删除proxy_pass
217 | proxy_pass http://127.0.0.1:3000;
218 | }
219 |
220 | # 样式资源等信息,用作配置浏览器缓存。请修改后段服务地址,或删除proxy_pass,并把js,css存到/www/所在位置
221 | location ~* \.(js|css|svg|woff|woff2)$ {
222 | # 对单个ip进行限速
223 | limit_req zone=req_ip burst=100 delay=200;
224 | # 对整个服务进行限速
225 | limit_req zone=req_svr burst=1000 delay=2000;
226 | # 对uri进行限速,防止刷单个资源,导致带宽被打爆
227 | limit_req zone=req_res burst=200 delay=1000;
228 | # lua_code_cache off;
229 | # access_by_lua_file /app/protect.lua;
230 | # log_by_lua_file /app/record.lua;
231 | # 设置浏览器资源过期时间
232 | expires 1d;
233 | # 向后端传递host名
234 | proxy_set_header Host $host;
235 | # 让浏览器每次请求检查资源是否过期
236 | add_header Cache-Control no-cache;
237 | access_by_lua_file /app/protect.ljbc;
238 | log_by_lua_file /app/record.ljbc;
239 | # 后段服务地址,请 根据实际情况修改。如果资源存在/www/所在的位置,请删除proxy_pass
240 | proxy_pass http://127.0.0.1:3000;
241 | }
242 |
243 | error_page 429 @429;
244 | location @429 {
245 | return 429 "error";
246 | }
247 |
248 | # location /control_group {
249 | # # 测速的对照组,生产环境请删除
250 | # proxy_set_header Host $host;
251 | # proxy_pass http://127.0.0.1:3000;
252 | # access_by_lua_block {
253 | # ngx.exit(429)
254 | # }
255 | # log_by_lua_block {
256 | # local a=0;
257 | # }
258 | # }
259 | }
260 |
261 | server {
262 | # 未匹配的域名,断开连接,防止源站被扫描
263 | listen 80 default_server;
264 | listen 443 ssl default_server;
265 | ssl_reject_handshake on;
266 | return 444;
267 | }
268 |
269 | server {
270 | # 测试用
271 | listen 3000;
272 | location / {
273 | return 200 'Ok';
274 | }
275 | }
276 | }
277 |
--------------------------------------------------------------------------------
/protect.lua:
--------------------------------------------------------------------------------
1 | function set_key(dict, key, value)
2 | local ok, err = dict:set(key, value)
3 | if not ok then
4 | ngx.log(ngx.ERR, "Set key", key, "err", err)
5 | ngx.exit(444)
6 | end
7 | end
8 |
9 | function str_concat(...)
10 | local str = {...}
11 | return table.concat(str, ':')
12 | end
13 |
14 | function protect(during, ttl, count_limit, bytes_limit, costs_limit)
15 | local dict = ngx.shared.traffic_stats
16 | local timestamp = ngx.now()
17 | local ip = ngx.var.limit_key
18 | local count_key = str_concat("count", during, ip)
19 | local bytes_key = str_concat("bytes", during, ip)
20 | local costs_key = str_concat("costs", during, ip)
21 | local last_time_key = str_concat("last", during, ip)
22 | local forbidden_key = str_concat("forbidden", during, ip)
23 |
24 | local last_time = dict:get(last_time_key)
25 | if last_time == nil or last_time + ttl < timestamp then
26 | set_key(dict, last_time_key, timestamp)
27 | set_key(dict, count_key, 0)
28 | set_key(dict, bytes_key, 0)
29 | set_key(dict, costs_key, 0)
30 | set_key(dict, forbidden_key, false)
31 | end
32 |
33 | local count = dict:get(count_key)
34 | if count ~= nil and count > tonumber(count_limit) then
35 | set_key(dict, forbidden_key, true)
36 | ngx.exit(444)
37 | end
38 |
39 | local bytes = dict:get(bytes_key)
40 | if bytes ~= nil and bytes > tonumber(bytes_limit) then
41 | set_key(dict, forbidden_key, true)
42 | ngx.exit(444)
43 | end
44 |
45 | local cost = dict:get(costs_key)
46 | if cost ~= nil and cost > tonumber(costs_limit) then
47 | set_key(dict, forbidden_key, true)
48 | ngx.exit(444)
49 | end
50 | end
51 |
52 | protect("hour", 3600, ngx.var.limit_count_per_hour, ngx.var.limit_bytes_per_hour, ngx.var.limit_costs_per_hour)
53 | protect("day", 3600 * 24, ngx.var.limit_count_per_day, ngx.var.limit_bytes_per_day, ngx.var.limit_costs_per_day)
54 |
--------------------------------------------------------------------------------
/record.lua:
--------------------------------------------------------------------------------
1 |
2 | function str_concat(...)
3 | local str = {...}
4 | return table.concat(str, ':')
5 | end
6 |
7 | function stats(during)
8 | local request_length = ngx.var.request_length
9 | local bytes_sent = ngx.var.bytes_sent
10 | local ip = ngx.var.limit_key
11 | local dict = ngx.shared.traffic_stats
12 | local count_key = str_concat("count", during, ip)
13 | local bytes_key = str_concat("bytes", during, ip)
14 | local costs_key = str_concat("costs", during, ip)
15 | dict:incr(count_key, 1)
16 | dict:incr(bytes_key, request_length + bytes_sent)
17 | dict:incr(costs_key, math.floor(ngx.var.request_time * 1000))
18 | --ngx.log(ngx.INFO, string.format('Usage %20s %5d %5d %5d',
19 | -- ip, 1, request_length + bytes_sent, math.floor(ngx.var.request_time * 1000)))
20 | end
21 |
22 | stats("hour")
23 | stats("day")
24 |
--------------------------------------------------------------------------------
/stats.lua:
--------------------------------------------------------------------------------
1 |
2 | function stats(during)
3 | local timestamp = ngx.now()
4 | local dict = ngx.shared.traffic_stats
5 | for _, val in pairs(dict:get_keys(0)) do
6 | local match = "last:"..during
7 | if string.sub(val, 1, #match) == match then
8 | local ip = string.sub(val, #match + 2, -1)
9 | local last_time = dict:get(val)
10 | local age = math.floor(timestamp - last_time)
11 | local count = dict:get("count:"..during..":"..ip)
12 | local bytes = dict:get("bytes:"..during..":"..ip)
13 | local costs = dict:get("costs:"..during..":"..ip)
14 | local forbidden = dict:get("forbidden:"..during..":"..ip)
15 | local output = string.format("%20s, %15s, %15d, %15d, %15d, %15d, %15s",
16 | ip, during, age, count, bytes, costs, forbidden)
17 | ngx.say(output)
18 | end
19 | end
20 | end
21 |
22 | ngx.say(string.format("%20s, %15s, %15s, %15s, %15s, %15s, %15s",
23 | 'ip', 'during', 'age', 'count', 'bytes', 'costs', 'forbidden'))
24 | stats("hour")
25 | stats("day")
26 |
--------------------------------------------------------------------------------
/wechat.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yinyue123/DK8sDDosFirewall/e55de6074a1f2906d2826f93bd6ca7e3de2ab18c/wechat.jpg
--------------------------------------------------------------------------------
/wrk.lua:
--------------------------------------------------------------------------------
1 | local random = math.random
2 |
3 | function request()
4 | local ip = string.format("%d.%d.%d.%d", random(0, 255), random(0, 255), random(0, 255), random(0, 255))
5 | wrk.headers["X-Forwarded-For"] = ip
6 | return wrk.format("GET", path)
7 | end
8 |
9 | -- wrk -s ./wrk.lua -c 500 -t 8 -d 600s -c 10 http://[target]
10 | -- wrk -s ./wrk.lua -c 500 -t 8 -d 600s -c 150 http://[target]
11 | -- wrk -s ./wrk.lua -c 500 -t 8 -d 600s -c 100000 http://[target]
12 |
--------------------------------------------------------------------------------