-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit a73654d
Showing
4 changed files
with
197 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
--------------------------------- | ||
|
||
XNOHAT DDoS FIREWALL | ||
|
||
Version: 1.1 | ||
|
||
xnohat@gmail.com | ||
|
||
----------------------------------- | ||
|
||
INSTRUCTION | ||
|
||
Notes: | ||
|
||
For CentOS only, modify yourself for other distros | ||
|
||
/!\ Must do: Stop all Web/HTTPD Services and Database Services for free resources first | ||
|
||
[!] Recommend: | ||
+ Using this firewall script on your reverse proxy | ||
+ Block all traffic to your main (upstream) server except traffic from Reverse Proxy | ||
+ Implement DNS Round robin with multiple reverse proxies to reduce DDoS load first | ||
+ Contact ISP to upgrade your server BANDWIDTH, RAM, CPU, HDD to maximum of your budget first. I suggest: 4-8 Cores CPU, 16-32 GB RAM, 50 GB SSD, Port 1Gbps NIC Bandwidth | ||
|
||
Step-by-step | ||
|
||
$ yum install epel-release | ||
|
||
$ yum install nload tmux | ||
|
||
$ yum install php php-pdo | ||
|
||
[+] Setting $logfile variable in logparser.php to path to your access.log | ||
|
||
[+] Modify logparser.php to match your access log format ( we need parse "ip of request" and "time of request" ), especially time of request must change to match SQLite time format look like 2016-11-05 01:35:24 | ||
Example log line from nginx: | ||
180.93.103.169 - - [05/Nov/2016:03:19:12 +0700] "GET / HTTP/1.0" 200 148608 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US)" "-" | ||
|
||
[+] Modify analyser.php, setting $threshold as number of request per $timewindow , any ip over this threshold will be | ||
block by iptables | ||
|
||
To get right Threshold for DDoS attacking you, do step below | ||
|
||
+ Use tcpdump to get packets attacking you $ tcpdump -vvvv -i <your_interface> -w <file_name.pcap> | ||
+ Open .pcap file in Wireshark: | ||
+ go to Edit -> Preference set: | ||
* "Show burst count for item rather than rate" set Enabled (check mark in the box) | ||
* set Burst rate resolution = Burst rate window size = 60000 miliseconds (1 min) | ||
+ Go Statistic -> ipv4 -> all addresses: burst rate is number of packets per minute, use average numbers (just guess!) to Threshold | ||
|
||
--------- | ||
|
||
$ chmod +x ./xnohatddosfirewall/runddosfirewall.sh | ||
|
||
$ chmod 777 ./xnohatddosfirewall | ||
|
||
Run script with sudo or root privilege: sudo ./runddosfirewall.sh | ||
follow guide on screen | ||
|
||
Press "Ctrl-b d" : to detach tmux | ||
|
||
Re-attach tmux by command $ tmux attach -t 0 | ||
|
||
Start all your services again |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
<?php | ||
|
||
echo "\n\t---------------------------------\n | ||
\tXNOHAT DDoS FIREWALL\n | ||
\tVersion: 1.1\n | ||
\txnohat@gmail.com\n | ||
-----------------------------------\n | ||
"; | ||
|
||
$serverip = '125.212.250.72'; | ||
$yourip = '1.53.194.96'; | ||
$exclude_ips = array($serverip, | ||
$yourip, | ||
|
||
'1.53.194.96', | ||
|
||
); | ||
|
||
$timewindow = 60; //unit: second - a splited interval time that requests are grouped in. For example one minute have 5000 requests | ||
$threshold = 5000; //threshold requests number per $timewindow | ||
$ipblocklist = array(); | ||
|
||
while(true){ | ||
|
||
exec('iptables -F BLOCKEDIP'); //flush chain rules | ||
exec("iptables-save | grep -v -- '-j BLOCKEDIP' | iptables-restore"); // delete all rules related to chain | ||
exec('iptables -X BLOCKEDIP'); //delete chain | ||
exec('iptables -N BLOCKEDIP'); //create chain | ||
exec("iptables -A BLOCKEDIP -j LOG --log-level 4 --log-prefix 'blockedip'"); //LOG any packets go to this BLOCKEDIP chain | ||
exec('iptables -A BLOCKEDIP -j DROP'); //DROP any packets go to this BLOCKEDIP chain | ||
|
||
//copy('access_log.db','access_log_for_analysis.db'); | ||
|
||
$db = new SQLite3('access_log.db'); | ||
//$db = new SQLite3(':memory:'); | ||
$db->query("PRAGMA synchronous = OFF"); | ||
$db->query("PRAGMA journal_mode = MEMORY"); | ||
$db->query("PRAGMA busy_timeout = 300000"); | ||
|
||
//$res_count_request = $db->query('SELECT remote_ip, count(remote_ip) AS request_num FROM accesslog GROUP BY remote_ip ORDER BY request_num DESC'); //load all request in database is VERY SLOW | ||
$res_count_request = $db->query('SELECT remote_ip, count(remote_ip) AS request_num FROM accesslog WHERE request_time BETWEEN "'.@date("Y-m-d H:i:s", time()-$timewindow).'" AND "'.@date("Y-m-d H:i:s", time()).'" GROUP BY remote_ip ORDER BY request_num DESC'); | ||
while ($row = $res_count_request->fetchArray()) { | ||
//print_r($row); | ||
if($row['request_num'] >= $threshold AND !in_array($row['remote_ip'],$exclude_ips)){ | ||
|
||
exec('iptables -A INPUT -s '.$row['remote_ip'].' -j BLOCKEDIP'); | ||
|
||
echo 'BLOCKED IP: '.$row['remote_ip'].' (REQ_NUM: '.$row['request_num'].")\n"; | ||
file_put_contents('blockedip.log',$row['remote_ip'].'-'.$row['request_num']."\n",FILE_APPEND); | ||
|
||
$ipblocklist[] = $row['remote_ip']; | ||
} | ||
} | ||
|
||
$db->close(); | ||
|
||
echo "SLEEP IN $timewindow seconds\n"; | ||
sleep($timewindow); | ||
|
||
} | ||
|
||
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
<?php | ||
|
||
$logfile = '/var/log/nginx/access.log'; | ||
|
||
unlink('access_log.db'); | ||
|
||
$db = new SQLite3('access_log.db'); | ||
//$db = new SQLite3(':memory:'); | ||
$db->query("PRAGMA synchronous = OFF"); | ||
$db->query("PRAGMA journal_mode = MEMORY"); | ||
$db->query("PRAGMA busy_timeout = 300000"); | ||
|
||
//Check log table exist or not | ||
$res_check_table_exist = $db->query("SELECT * FROM sqlite_master WHERE name = 'accesslog' and type='table' "); | ||
if(!$res_check_table_exist->fetchArray()){ // Not have table accesslog | ||
//echo "Table Not exist"; | ||
//Create Table accesslog | ||
$db->exec('CREATE TABLE accesslog (remote_ip varchar(255), request_time NUMERIC)'); | ||
$db->exec("CREATE INDEX accesslog_index ON accesslog(remote_ip,request_time)"); | ||
echo "Table accesslog has been created \r\n"; | ||
} | ||
|
||
//Follow Log | ||
$size = filesize($logfile); //set to current file size to move disk read cursor to end of file | ||
while (true) { | ||
clearstatcache(); | ||
$currentSize = filesize($logfile); | ||
if ($size == $currentSize) { | ||
usleep(100); | ||
continue; | ||
} | ||
|
||
$fh = fopen($logfile, "r"); | ||
fseek($fh, $size); | ||
|
||
while ($line = fgets($fh)) { | ||
|
||
// process the line read. | ||
if($line <> ''){ | ||
//-----Clear wasted character----- | ||
$clear_char = array('[',']'); | ||
$line = str_replace($clear_char,'',$line); //strip special chars | ||
|
||
//-----Parse Log Line----- | ||
$arr_log_line = explode(' ',$line); | ||
//var_dump($arr_log_line);continue; | ||
$remote_ip = $arr_log_line[0]; | ||
$request_time = @date("Y-m-d H:i:s", @strtotime(str_replace('/', '-', substr_replace($arr_log_line[3], ' ', -9,1)))); //original nginx time look like 05/Nov/2016:01:35:24 , remember change for apache , SQLite format must look like 2016-11-05 01:35:24 | ||
$db->exec('INSERT INTO accesslog (remote_ip, request_time) VALUES ("'.$remote_ip.'","'.$request_time.'")'); //insert request to DB | ||
//echo $remote_ip.' - '.$request_time."\r\n"; | ||
echo $line; | ||
} | ||
|
||
} | ||
|
||
fclose($fh); | ||
$size = $currentSize; | ||
} | ||
|
||
$db->close(); | ||
|
||
|
||
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#!/bin/sh | ||
tmux new-session -n 'xnohatDDoSFirewall' -d 'echo -e "Press Ctrl-b LEFT to move Cursor to this panel\nRun Command: php analyser.php"; bash -i' #create window with 1st panel | ||
tmux split-window -h -p 50 'nload; bash -i' #split window horizon to 50% | ||
tmux split-window -v -p 70 'top; bash -i' #split 'new created previous panel' to 2 panel with new create panel is 60% of previous panel | ||
tmux split-window -v -p 40 'php logparser.php; bash -i' #split previous created panel to 2 panel with new create panel is 30% of previous panel | ||
#tmux select-pane -t +1 #move focus to 1st panel | ||
#tmux send-keys 'top; bash -i' Enter #run some command in 1st panel | ||
tmux -2 attach-session -d |