'.$status.'
'.($message ? ''.$message.'
' : '').'Ray ID: '.md5($status.$message.time()).' - Powered by CloudFirewall
├── .github
└── dependabot.yml
├── .gitignore
├── CloudFirewallWHMCS.rar
├── LICENSE
├── README.md
├── composer.json
├── examples.php
├── src
└── CloudFirewall.php
├── vendor
├── autoload.php
└── composer
│ ├── ClassLoader.php
│ ├── LICENSE
│ ├── autoload_classmap.php
│ ├── autoload_namespaces.php
│ ├── autoload_psr4.php
│ ├── autoload_real.php
│ ├── autoload_static.php
│ └── installed.json
└── versions.json
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: composer
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | time: "11:00"
8 | open-pull-requests-limit: 10
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor/
2 | /CloudFirewallWHMCS.rar
3 | /versions.json
--------------------------------------------------------------------------------
/CloudFirewallWHMCS.rar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xaronnn/CloudFirewall/0cfbfea803826bad0aaa377c4b0c53a644fb215c/CloudFirewallWHMCS.rar
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 CloudFirewall - Uğur PEKESEN
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CloudFirewall
2 | Protect your website against bots/spam/flood, sql/xss injection attacks as using Cloudflare service.
3 |
4 | 
5 | 
6 | 
7 | 
8 | 
9 | 
10 |
11 |
12 | # Installation
13 |
14 | `composer require xaron/cloud-firewall`
15 |
16 | # WHMCS Module
17 |
18 | `Download: https://github.com/0x5841524f4e/CloudFirewall/raw/master/CloudFirewallWHMCS.rar`
19 |
20 | `Export files to your main WHMCS directory.`
21 |
22 | # Examples
23 |
24 | ```php
25 | changeSecurityLevel('medium', 'zone_id (Not required if already set in constructor)');
40 |
41 | /*
42 | Create access rule.
43 | Actions: [block, challenge, whitelist, js_challenge]
44 | */
45 | $firewall->createAccessRule('31.13.37.31', 'challenge');
46 |
47 | /*
48 | Enabling block SQL injection attacks and it will ban from Cloudflare.
49 | Parameters: sqlInjectionBlock(true if you want request ip ban from Cloudflare. default is true.)
50 | */
51 | $firewall->sqlInjectionBlock();
52 |
53 | /*
54 | Enabling block XSS injection attacks and it will ban from Cloudflare.
55 | Parameters: xssInjectionBlock(true if you want request ip ban from Cloudflare. default is true.)
56 | */
57 | $firewall->xssInjectionBlock();
58 |
59 | /*
60 | Enabling block cookie steal attacks.
61 | Parameters: cookieStealBlock(true if you want request ip ban from Cloudflare. default is false.)
62 | */
63 | $firewall->cookieStealBlock();
64 |
65 | /*
66 | Enabling anti flood.
67 | Parameters: antiFlood(requestPerSecond, badRequestChance, badRequestResetInXseconds, banFromCloudflare)
68 | */
69 | $firewall->antiFlood(1, 3, 5, true);
70 |
71 | /*
72 | Get script execution time.
73 | Info: Please write at the bottom of the page.
74 | Usage: echo($firewall->benchmark());
75 | */
76 | $firewall->benchmark();
77 | ```
78 |
79 | # Requirements
80 |
81 | - [x] PHP >= 7.1.*
82 | - [x] cURL extension
83 | - [x] OpenSSL extension
84 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "xaron/cloud-firewall",
3 | "type": "library",
4 | "description": "Protect your website against bots/spam/flood as using Cloudflare service.",
5 | "keywords": ["php", "cloudflare", "ddos", "block", "firewall", "sql", "injection", "xss", "flood", "protection"],
6 | "homepage": "https://xaron.us",
7 | "license": "MIT",
8 | "authors": [
9 | {
10 | "name": "Uğur PEKESEN",
11 | "email": "me@xaron.us",
12 | "homepage": "http://xaron.us",
13 | "role": "Developer"
14 | }
15 | ],
16 | "require": {
17 | "php": "^7.1"
18 | },
19 | "autoload": {
20 | "psr-4": {
21 | "CF\\": "src"
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/examples.php:
--------------------------------------------------------------------------------
1 | changeSecurityLevel('medium', 'zone_id (Not required if already set in constructor)');
16 |
17 | /*
18 | Create access rule.
19 | Actions: [block, challenge, whitelist, js_challenge]
20 | */
21 | $firewall->createAccessRule('31.13.37.31', 'block');
22 |
23 |
24 | /*
25 | Enabling block SQL injection attacks and it will ban from Cloudflare.
26 | Parameters: sqlInjectionBlock(true if you want request ip ban from Cloudflare. default is true.)
27 | */
28 | $firewall->sqlInjectionBlock();
29 |
30 | /*
31 | Enabling block XSS injection attacks and it will ban from Cloudflare.
32 | Parameters: xssInjectionBlock(true if you want request ip ban from Cloudflare. default is true.)
33 | */
34 | $firewall->xssInjectionBlock();
35 |
36 | /*
37 | Enabling block cookie steal attacks.
38 | Parameters: cookieStealBlock(true if you want request ip ban from Cloudflare. default is true.)
39 | */
40 | $firewall->cookieStealBlock();
41 |
42 | /*
43 | Enabling anti flood.
44 | Parameters: antiFlood(requestPerSecond, badRequestChance, badRequestResetInXseconds, banFromCloudflare)
45 | */
46 | $firewall->antiFlood(1, 3, 5, true);
47 |
48 | /*
49 | Get script execution time.
50 | Info: Please write at the bottom of the page.
51 | Usage: echo($firewall->benchmark());
52 | */
53 | $firewall->benchmark();
54 | ?>
--------------------------------------------------------------------------------
/src/CloudFirewall.php:
--------------------------------------------------------------------------------
1 |
7 | * @version 1.0.2
8 | */
9 |
10 | namespace CF;
11 |
12 | class CloudFirewall {
13 |
14 | private $email, $key, $zone, $curl, $debug;
15 | protected $version = '1.0.2';
16 |
17 | /**
18 | * CloudFirewall constructor.
19 | *
20 | * @param string $email The your Cloudflare email address.
21 | * @param string $key The your Cloudflare API key.
22 | * @param string $zone The your Cloudflare zone.
23 | */
24 | public function __construct(string $email, string $key, string $zone = null) {
25 | $this->email = $email;
26 | $this->key = $key;
27 | $this->zone = $zone;
28 | $this->benchmarkStart = self::benchmarkStart();
29 | if(isset($_SESSION)) {
30 | $_SESSION['CloudFirewall-Client-IP'] = $this->getIP();
31 | } else {
32 | session_start();
33 | $_SESSION['CloudFirewall-Client-IP'] = $this->getIP();
34 | }
35 | set_error_handler(function($errno, $errstr, $errfile, $errline) {
36 | self::abort(500, 'Error: '.$errstr.' - Error Code '.$errno.'
File: '.$errfile.' - Line '.$errline.'');
37 | });
38 | set_exception_handler(function($exception) {
39 | self::abort(500, $exception->getMessage());
40 | });
41 | header("x-powered-by: CloudFirewall WAF");
42 | header("x-cloudfirewall: v".$this->version);
43 | self::requirements();
44 | }
45 |
46 | /**
47 | * Changes security level on your zone.
48 | *
49 | * @param string $value The security levels [essentially_off, low, medium, high, under_attack].
50 | * @param string $zone The zone id.
51 | * @return mixed Bool False if request is not responded. JSON if request success.
52 | */
53 | public function changeSecurityLevel(string $value = 'low', string $zone = null) {
54 | if(self::checkSecurityLevel($value)) {
55 | if($zone) {
56 | return $this->connect('https://api.cloudflare.com/client/v4/zones/'.$zone.'/settings/security_level', 'PATCH', array('value' => $value));
57 | } else {
58 | return $this->connect('https://api.cloudflare.com/client/v4/zones/'.$this->zone.'/settings/security_level', 'PATCH', array('value' => $value));
59 | }
60 | } else {
61 | return false;
62 | }
63 | }
64 |
65 | /**
66 | * Create rule to specified IP address with an action.
67 | *
68 | * @param string $value The IP(v4/v6) address.
69 | * @param string $action The action [block, challenge, whitelist, js_challenge].
70 | * @return mixed Bool False if request is not responded. JSON if request success.
71 | */
72 | public function createAccessRule(string $value, string $action) {
73 | if(self::checkIP($value) && self::checkAccessRule($action)) {
74 | return $this->connect('https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules', 'POST', array('mode' => $action, 'configuration' => array('target' => (self::checkIPv4($value) ? 'ip' : ($this->checkIPv4($value) ? 'ip6' : null)), 'value' => $value), 'notes' => 'Created by CloudFirewall'));
75 | } else {
76 | return false;
77 | }
78 | }
79 |
80 | /**
81 | * Enabling block SQL injection attacks.
82 | *
83 | * @param bool $ban Default is true and it will ban from Cloudflare.
84 | * @return none.
85 | */
86 | public function sqlInjectionBlock(bool $ban = true) {
87 | foreach ($_GET as $key => $value) {
88 | if (is_array($value)) {
89 | $flattened = self::arrayFlatten($value);
90 | foreach ($flattened as $sub_key => $sub_value) {
91 | $this->sqlCheck($sub_value, "_GET", $sub_key, $ban);
92 | }
93 | } else {
94 | $this->sqlCheck($value, "_GET", $key, $ban);
95 | }
96 | }
97 | foreach ($_POST as $key => $value) {
98 | if (is_array($value)) {
99 | $flattened = self::arrayFlatten($value);
100 | foreach ($flattened as $sub_key => $sub_value) {
101 | $this->sqlCheck($sub_value, "_POST", $sub_key, $ban);
102 | }
103 | } else {
104 | $this->sqlCheck($value, "_POST", $key, $ban);
105 | }
106 | }
107 | foreach ($_COOKIE as $key => $value) {
108 | if (is_array($value)) {
109 | $flattened = self::arrayFlatten($value);
110 | foreach ($flattened as $sub_key => $sub_value) {
111 | $this->sqlCheck($sub_value, "_COOKIE", $sub_key, $ban);
112 | }
113 | } else {
114 | $this->sqlCheck($value, "_COOKIE", $key, $ban);
115 | }
116 | }
117 | }
118 |
119 | /**
120 | * Enabling block XSS injection attacks.
121 | *
122 | * @param bool $ban Default is true and it will ban from Cloudflare.
123 | * @return none.
124 | */
125 | public function xssInjectionBlock(bool $ban = true) {
126 | foreach ($_GET as $key => $value) {
127 | if (is_array($value)) {
128 | $flattened = self::arrayFlatten($value);
129 | foreach ($flattened as $sub_key => $sub_value) {
130 | $this->xssCheck($sub_value, "GET", $sub_key, $ban);
131 | $this->htmlCheck($sub_value, "GET", $sub_key, $ban);
132 | }
133 | } else {
134 | $this->xssCheck($value, "GET", $key, $ban);
135 | $this->htmlCheck($value, "GET", $key, $ban);
136 | }
137 | }
138 | foreach ($_POST as $key => $value) {
139 | if (is_array($value)) {
140 | $flattened = self::arrayFlatten($value);
141 | foreach ($flattened as $sub_key => $sub_value) {
142 | $this->xssCheck($sub_value, "POST", $sub_key, $ban);
143 | $this->htmlCheck($sub_value, "POST", $sub_key, $ban);
144 | }
145 | } else {
146 | $this->xssCheck($value, "POST", $key, $ban);
147 | $this->htmlCheck($value, "POST", $key, $ban);
148 | }
149 | }
150 | foreach ($_COOKIE as $key => $value) {
151 | if (is_array($value)) {
152 | $flattened = self::arrayFlatten($value);
153 | foreach ($flattened as $sub_key => $sub_value) {
154 | $this->xssCheck($sub_value, "COOKIE", $sub_key, $ban);
155 | $this->htmlCheck($sub_value, "COOKIE", $sub_key, $ban);
156 | }
157 | } else {
158 | $this->xssCheck($value, "COOKIE", $key, $ban);
159 | $this->htmlCheck($value, "COOKIE", $key, $ban);
160 | }
161 | }
162 | }
163 |
164 | /**
165 | * Enabling block steal cookie attacks.
166 | *
167 | * @param bool $ban Default is false and it will ban from Cloudflare.
168 | * @return none.
169 | */
170 | public function cookieStealBlock(bool $ban = false) {
171 | if (isset($_SESSION)) {
172 | if (!isset($_SESSION['CloudFirewall-Client-IP'])) {
173 | $_SESSION['CloudFirewall-Client-IP'] = $this->getIP();
174 | } else {
175 | if ($_SESSION['CloudFirewall-Client-IP'] != $this->getIP()) {
176 | if($ban) {
177 | $this->createAccessRule($this->getIP(), 'block');
178 | }
179 | session_destroy();
180 | self::abort(403, 'Cookie Stealing Detected');
181 | }
182 | }
183 | }
184 | }
185 |
186 | public function antiFlood(int $requestPerSecond = 2, int $badRequestChance = 3, int $badRequestReset = 5, bool $ban = false) {
187 | if(isset($_SESSION)) {
188 | if(!isset($_SESSION['CloudFirewall-Client-LastRequestTime']) && !isset($_SESSION['CloudFirewall-Client-BadRequest'])) {
189 | $_SESSION['CloudFirewall-Client-LastRequestTime'] = time();
190 | $_SESSION['CloudFirewall-Client-BadRequest'] = 0;
191 | } else {
192 | if(isset($_SESSION['CloudFirewall-Client-LastBadRequestTime'])) {
193 | if($_SESSION['CloudFirewall-Client-LastBadRequestTime']+$badRequestReset <= time()) {
194 | unset($_SESSION['CloudFirewall-Client-LastBadRequestTime']);
195 | $_SESSION['CloudFirewall-Client-BadRequest'] = 0;
196 | }
197 | }
198 | if($_SESSION['CloudFirewall-Client-BadRequest'] >= $badRequestChance) {
199 | if($ban) {
200 | $this->createAccessRule($this->getIP(), 'block');
201 | }
202 | $_SESSION['CloudFirewall-Client-LastBadRequestTime'] = time()+$requestPerSecond;
203 | self::abort(403, 'Flood Detected');
204 | }
205 | if($_SESSION['CloudFirewall-Client-LastRequestTime'] >= time()) {
206 | $_SESSION['CloudFirewall-Client-LastBadRequestTime'] = time()+$requestPerSecond;
207 | $_SESSION['CloudFirewall-Client-BadRequest'] = $_SESSION['CloudFirewall-Client-BadRequest']+1;
208 | }
209 | }
210 | $_SESSION['CloudFirewall-Client-LastRequestTime'] = time();
211 | }
212 | }
213 |
214 | /**
215 | * Enable debug mode.
216 | *
217 | * @return none.
218 | */
219 | public function debug(bool $debug = false) {
220 | $this->debug = $debug;
221 | }
222 |
223 | /**
224 | * Get script execution time in seconds.
225 | *
226 | * @return float Script executed in X seconds.
227 | */
228 | public function benchmark() {
229 | return self::benchmarkEnd($this->benchmarkStart);
230 | }
231 |
232 | private static function abort(int $status, string $message = null) {
233 | $statusses = ['404', '403', '500', '777'];
234 | if(in_array($status, $statusses)) {
235 | header('HTTP/1.0 '.$status.' Forbidden');
236 | die('