TA的每日心情 | 开心 2021-3-12 23:18 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
Flood攻击,俗称洪水攻击,所谓拒绝服务攻击中的一种。
它利用TCP协议的设计上的缺陷,通过特定方式发送大量的TCP请求从而导致受攻击的一方CPU超负荷或内存不足。 使用防火墙是防御Flood攻击的最有效的方法之一。
在学习论坛mvnforum-1.1源码时,发现其中有防Flood攻击的处理,它是通过限制每个IP每小时的HTTP请求数来防止Flood攻击的。
其原理也用来防止其它的攻击论坛的手段如:不停的发贴,一个iP注册多个账号等。
下面来看看具体的源码。
一、首先在MVNForumGlobal.java中定义一些全局变量,用来表示需要防止的动作:
public final static Integer FLOOD_ID_NEW_POST_PER_IP = new Integer(1000);
public final static Integer FLOOD_ID_NEW_MEMBER_PER_IP = new Integer(1001);
public final static Integer FLOOD_ID_LOGIN_PER_IP = new Integer(1002);
public final static Integer FLOOD_ID_NEW_MESSAGE_PER_IP = new Integer(1003);
public final static Integer FLOOD_ID_NEW_POST_PER_MEMBER = new Integer(1004);
public final static Integer FLOOD_ID_HTTP_REQUEST_PER_IP = new Integer(1005);//http请求动作
在MVNForumConfig.java中设置了值,论坛启动时会加载。 FloodControl.setOption(MVNForumGlobal.FLOOD_ID_NEW_MEMBER_PER_IP, maxMembersPerHourPerIP);
FloodControl.setOption(MVNForumGlobal.FLOOD_ID_NEW_POST_PER_IP, maxPostsPerHourPerIP);
FloodControl.setOption(MVNForumGlobal.FLOOD_ID_NEW_POST_PER_MEMBER, maxPostsPerHourPerMember);
FloodControl.setOption(MVNForumGlobal.FLOOD_ID_LOGIN_PER_IP, maxLoginsPerHourPerIP);
FloodControl.setOption(MVNForumGlobal.FLOOD_ID_NEW_MESSAGE_PER_IP, maxMessagesPerHourPerIP);
FloodControl.setOption(MVNForumGlobal.FLOOD_ID_HTTP_REQUEST_PER_IP, maxHttpRequestsPerHourPerIP);
二、在web.xml文件中注册一个Servlet控制器ForumUserServlet,任何用户对论坛的访问都要经过它的检验。
<servlet>
<servlet-name>ForumUserServlet</servlet-name>
<servlet-class>com.mvnforum.user.ForumUserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ForumUserServlet</servlet-name>
<url-pattern>/mvnforum/*</url-pattern>
</servlet-mapping>
下面是ForumUservlet.java中的代码:
String currentIP = request.getRemoteAddr();//获取客户端的IP
// Control the HTTP request, we dont want user to try too many request
//检查这个IP是否发出了太多的请求。
try {
FloodControl.ensureNotReachMaximum(MVNForumGlobal.FLOOD_ID_HTTP_REQUEST_PER_IP, currentIP);
} catch (FloodException fe) {
getServletContext().getRequestDispatcher("/mvnplugin/mvnforum/max_http_request.jsp").forward(request, response);
return;
}
//增加一个请求计数
FloodControl.increaseCount(MVNForumGlobal.FLOOD_ID_HTTP_REQUEST_PER_IP, currentIP);
三、主要是这个文件: - package net.myvietnam.mvncore.security;
- import java.util.*;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import net.myvietnam.mvncore.exception.FloodException;
- import net.myvietnam.mvncore.util.DateUtil;
- /**
- * This class is used to control the number of actions per hour. This is usually
- * used to prevent the flood of any action. You should call FloodControl.setOption()
- * when your application is inited.
- * Note that the action id from 0 to 999 is belong to mvnCore, application used it
- * should not use the value in this range
- */
-
- public class FloodControl {
- private static Log log = LogFactory.getLog(FloodControl.class);
- /** The value from 0 to 999 should belong to mvnCore */
- public static int MAX_MVNCORE_ACTION_ID = 999;
- private static Map actionControlMap = new TreeMap();
- static final long REMOVE_INTERVAL = DateUtil.MINUTE * 2;//2 minutes
- private FloodControl() {
- }
-
- /**
- * To set the mamximum number of actions per hour for an action.
- * If the caller does not call this method, the the action has no limit
- * @param action Integer the action that want to set the option
- * @param actionsPerHour int the maximum number of actions per hour
- */
-
- public static void setOption(Integer action, int actionsPerHour) {
- getControlledAction(action).setActionsPerHour(actionsPerHour);
- }
- public static int getActionsPerHour(Integer action) {
- return getControlledAction(action).getActionsPerHour();
- }
- /**
- * Check that an action of an IP has reach the maximum number of allowed times
- * @param action Integer the action to check
- * @param strIP String the IP to check
- * @return boolean true if it has reached the maximum
- */
-
- public static boolean reachMaximum(Integer action, String strIP) {
- return getControlledAction(action).reachMaximum(strIP);
- }
- /**
- * This is a utility method to ensure that the action has not reached the mamximum.
- * It calls the method reachMaximum and throw an exception if it reached the maximum.
- * A program could use this method to use the default error message, otherwise
- * it has to use reachMaximum
- * @param action Integer the action to ensure
- * @param strIP String the IP to ensure
- * @throws FloodException if it reached the maximum
- * @see FloodControl#reachMaximum(Integer, String)
- */
- public static void ensureNotReachMaximum(Integer action, String strIP) throws FloodException {
- if (reachMaximum(action, strIP)) {
- log.info("Attempt to exceed the maximum number of actions: ActionID = " + action + " and IP = " + strIP);
- //@todo : localize me
- throw new FloodException("You have reached the maximum number of actions for this page
- (actionID = " + action + "). Please try this page later. This is to prevent forum from being flooded.");
- }
- }
- /**
- * Increase the number of action. This method should be called the the program
- * has done this action. Forget to call this method will void the reachMaximum method.
- * @param action Integer the action to increase the number of times
- * @param strIP String the IP to increase the number of times
- */
- public static void increaseCount(Integer action, String strIP) {
- getControlledAction(action).increaseCount(strIP);
- }
- /**
- * Reset the action history. This method is useful in such a case in the login
- * process that after login successfully, the value should be reset. Please note
- * that this is just an example and usually no need to use this method.
- * @param action Integer
- * @param strIP String
- */
- public static void resetActionHistory(Integer action, String strIP) {
- getControlledAction(action).resetActionHistory(strIP);
- }
- /**
- * Return the instance of ControlledAction for the action. It will create
- * new instance if no previous instance for this action exist.
- * @param action Integer
- * @return ControlledAction
- */
- private static synchronized ControlledAction getControlledAction(Integer action) {
- ControlledAction controlledAction = (ControlledAction)actionControlMap.get(action);
- if (controlledAction == null) {
- controlledAction = new ControlledAction();
- actionControlMap.put(action, controlledAction);
- }
- return controlledAction;
- }
- }
- /**
- * For one action that handles a list of all IP
- */
- class ControlledAction {
- private int actionsPerHour = 0;//缺省情况下,对每小时的动作数不作限制。
- private Map ipMap = new TreeMap();
- private long lastRemoveTime = 0;
- void setActionsPerHour(int actionsPerHour) {
- if (actionsPerHour >= 0) {
- this.actionsPerHour = actionsPerHour;
- }
- }
- int getActionsPerHour() {
- return actionsPerHour;
- }
- boolean reachMaximum(String strIP) {
- removeTimeoutControlledIP();
- return getControlledIP(strIP).reachMaximum();
- }
- void increaseCount(String strIP) {
- removeTimeoutControlledIP();
- getControlledIP(strIP).increaseCount();
- }
- void resetActionHistory(String strIP) {
- removeTimeoutControlledIP();
- getControlledIP(strIP).resetActionHistory();
- }
- private synchronized ControlledIP getControlledIP(String strIP) {
- ControlledIP controlledIP = (ControlledIP)ipMap.get(strIP);
- if (controlledIP == null) {
- controlledIP = new ControlledIP(actionsPerHour);
- ipMap.put(strIP, controlledIP);
- } else {
- // there is a ControlledIP, update the actionsPerHour
- controlledIP.setActionsPerHour(actionsPerHour);
- }
- return controlledIP;
- }
- private synchronized void removeTimeoutControlledIP() {
- long now = System.currentTimeMillis();
- if ((now - lastRemoveTime) > FloodControl.REMOVE_INTERVAL) {
- lastRemoveTime = now;
- Collection ipList = ipMap.values();
- for (Iterator iter = ipList.iterator(); iter.hasNext(); ) {
- ControlledIP currentControlledIP = (ControlledIP)iter.next();
- if (now - currentControlledIP.getLastIncrementTime() > DateUtil.HOUR) {
- iter.remove();
- }
- }
- }
- }
- }
- /**
- * For one action per one IP
- */
- class ControlledIP {
- private int actionsPerHour = 0;//缺省不作限制。
- private long lastRemoveTime = 0;
- private long lastIncrementTime = 0;
- private ArrayList actionHistoryList = new ArrayList();
- ControlledIP(int actionsPerHour) {
- if (actionsPerHour >= 0) {
- this.actionsPerHour = actionsPerHour;
- }
- }
- void setActionsPerHour(int actionsPerHour) {
- if (actionsPerHour >= 0) {
- this.actionsPerHour = actionsPerHour;
- }
- }
- long getLastIncrementTime() {
- return lastIncrementTime;
- }
- void increaseCount() {
- long now = System.currentTimeMillis();
- lastIncrementTime = now;
- actionHistoryList.add(new Long(now));
- }
- void resetActionHistory() {
- lastRemoveTime = 0;
- lastIncrementTime = 0;
- actionHistoryList.clear();
- }
- boolean reachMaximum() {
- if (actionsPerHour == 0) {//unlimited 没有限制。
- return false;
- }
- if (actionHistoryList.size() < actionsPerHour) {
- return false;
- }
- // now try to remove timeout actions
- removeTimeoutActions();
- return (actionHistoryList.size() >= actionsPerHour);
- }
- private synchronized void removeTimeoutActions() {
- long now = System.currentTimeMillis();
- if (now - lastRemoveTime > FloodControl.REMOVE_INTERVAL) {
- lastRemoveTime = now;
- for (Iterator iter = actionHistoryList.iterator(); iter.hasNext(); ) {
- Long currentAction = (Long)iter.next();
- if ((now - currentAction.longValue()) > DateUtil.HOUR) {
- iter.remove();
- }
- } //for
- }
- }
- }
复制代码
源码下载:http://file.javaxxz.com/2014/10/2/023733938.zip |
|