/*
 * Author: Saeed Ghiassy
 * Date:    Mon Sep 21 03:27:34 BST 2009
 * Version:  0.1
 * 
 * Description:  This java class tries to stop SSH Brute Force Attacks 
 * 				 by look into log file created by SSH daemon.
 * 				 it checks number of failure login attempts,and if it is more than
 * 				 10 times failure attempt, the IP will be categorised as an Attacker IP.
 * 				 Then the IP address will be added to /etc/hosts.deny to be blocked for
 * 				 Any further attempts.Also the list file creates for user information.
 *
 * 
 *   ##### Example Log file can be downloaded from here  #########     
 */

import java.io.*;
import java.util.*;
import java.util.regex.*;

public class jssh_bruteforce_blocker 
{
	//Regular expression to find IP address
	private final static String IP_REGEX = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}";
	private final static String failure_msg_REGEX = "Failed password";
	
	private static HashMap<String,  Integer > ipaddresses = new HashMap<String, Integer>();
	private static ArrayList<String> blacklist = new ArrayList<String>();
	
	public static void main(String[]args) throws IOException
	{
		if(args.length != 1)
		{
			System.err.println("Usage: java jssh_bruteforce_blocker <log file>");
			System.exit(-1);			
		}
		String m_filename = args[0];
		File m_logfile = new File(m_filename);
		if(m_logfile.exists())
		{
		System.out.println("[+]Log file located: " + m_logfile.getAbsolutePath());
		}else{
			System.err.println("[-]Log file not found!\n[-]Terminating application.");
			System.exit(-1);
		}
		//simple check for validate log file
		if(!validate_logfile(m_logfile)){
			System.err.println("[-]Log file validation failed.\n[-]Terminating application.");
			System.exit(-1);
		}
		
		detect_failure_login(m_logfile);
		gen_report();
		save_to_file();
		
		System.out.println("[+]All Tasks successfully done.\n[!]Terminating application. :-)");
		
	}//-- end of main

///////////////validating log file by looking for "sshd" string
	public static boolean validate_logfile(File logfile) throws IOException
	{
		
		System.out.println("[+]Validating Log file....");
		
		int count=0;
		boolean flag = false;
		BufferedReader stdin = new BufferedReader(new FileReader(logfile));
		String read;
		while((read = stdin.readLine()) != null)
		{			
			if(read.contains("sshd"))
			{
				count++;
			}
			if(count >= 3)
			{
				System.out.println("[+]Log file seems to be valid :-)");
				flag = true;
				break;
			}
		}		
		stdin.close();		
		return flag;
	}//-- end of validate function

/////////////Detect Failure Login attempts
	public static void detect_failure_login(File logfile)throws IOException
	{
		System.out.println("[+]Reading Log file contents, please wait...");
		BufferedReader stdin =  new BufferedReader(new FileReader(logfile));
		
		Pattern pattern_failure = Pattern.compile(failure_msg_REGEX,Pattern.CASE_INSENSITIVE);
		Pattern pattern_ip = Pattern.compile(IP_REGEX,Pattern.CASE_INSENSITIVE);
				
		String input,ip;
		
		while((input = stdin.readLine())!=null)
		{
			//Searching for Failed password String	
			Matcher matcher = pattern_failure.matcher(input);
				if(matcher.find())
				{
					//System.out.println("####found### "+ matcher.group());
					
					//Searching for ip addresses in failure line
					Matcher ip_matcher = pattern_ip.matcher(input);
					if(ip_matcher.find())
					{
						ip = ip_matcher.group();
						//System.out.println("IP address: " + ip);
						
						//Check if ip is already added to list increase its attempt times
						//otherwise add the new ip to list
						if(ipaddresses.containsKey(ip))
						{
							int count = ipaddresses.get(ip);
							count++;
							ipaddresses.remove(ip);
							ipaddresses.put(ip, count);
							
							
						}else{
							ipaddresses.put(ip, 1);
						}//-- end else
					}
				}// -- end searching if				
		}//-- End of while loop
		System.out.println("[+]Searching process completed.");
		
		//System.out.println(ipaddresses);
		stdin.close();
		
	}//-- end of detect_failure_login


////////////Generating Report
	public static void gen_report()
	{
		Set mySet = ipaddresses.entrySet();
		
		System.out.println("[+]Generating report.");
		System.out.println("=======================================================");
		System.out.println("IP Address\t\tNumber of Failure Attempts");
		System.out.println("____________\t\t__________________________");
		Iterator i = mySet.iterator();
		while(i.hasNext())
		{
			Map.Entry map = (Map.Entry)i.next();
			System.out.print(map.getKey()+"\t\t\t" + map.getValue());
			int x = Integer.parseInt(map.getValue().toString());
			if(x > 10 )
			{
				System.out.print("\t\t!! BruteForce Attack Detected !!");
				blacklist.add(map.getKey().toString());
			}
			System.out.println();
		}
		System.out.println("=======================================================");

		
	}// End of report
	
///////////////Save Attackers ip to File
	public static void save_to_file() throws IOException
	{
		System.out.println("[+]Creating Blacklist file.");
		File blocklist = new File("blocklist.txt");
		BufferedWriter fwout = null;
		FileWriter fstream = null;
		
		if(blocklist.createNewFile())
		{
			fstream = new FileWriter(blocklist,true);
			fwout = new BufferedWriter(fstream);
			fwout.write("##################################################\n");
			fwout.write("Generated by: jssh_bruteforce_blocker\n");
			fwout.write("Date:    " + new Date().toString() + "\n");
			fwout.write("##################################################\n\n");
			fwout.flush();
		}else{
			System.out.println("[-]Blacklist file already exist.\n[+]Adding to the End of file.");
			fstream = new FileWriter(blocklist,true);
			fwout = new BufferedWriter(fstream);
		}
		
		for(int i=0; i< blacklist.size();i++)
		{
			fwout.write("IP Address:  " + blacklist.get(i) 
						+"\t\tAdded Date: " + new Date().toString() + "\n");
			if(i%100==0)
			{
				fwout.flush();
			}
		}
		
		fwout.close();
		
/* ***********************************************************
 * Adding Attacker IPs to "/etc/hosts.deny"  
 * This will stop them to connect to server again		
 * ROOT ACCESS NEEDED TO CHANGE THIS FILE
 *************************************************************/
		File hosts = new File("/etc/hosts.deny");
		if(hosts.exists())
		{
			System.out.println("[+]Adding attackers IP to /etc/hosts.deny");
			FileWriter mywriter = new FileWriter(hosts, true);
			BufferedWriter mybw = new BufferedWriter(mywriter);
			
			for(int i=0;i<blacklist.size();i++){
				//mybw.write("sshd: " + blacklist.get(i) + "\n");
				//Blocking access to all Services
				mybw.write("ALL: " + blacklist.get(i) + "\n");
				mybw.flush();
			}
			
		}else{
			System.out.println("[-]Hosts File not found in defined path: /etc/hosts.deny");
		}
		
	}//-- End of save to file function	
	
	
}// end of file