文档章节

t-io im小站攻防实录

talent-tan
 talent-tan
发布于 2017/06/01 10:37
字数 1166
阅读 3588
收藏 32

http://t-io.org:9292/newim/index.html是作者用tio写的一个web im小站,目前代码还在开发阶段,问题也比较多,暂未开源(t-io刚开源时的时候问题也不少,尤其是一些调试代码,眼尖的网友很容易看出来),废话少说,说一下本小站的一些攻防故事吧。

  1. 跨站脚本攻击

    这个比较简单,直接用对html进行转义就好,譬如:
    org.apache.commons.lang3.StringEscapeUtils.escapeHtml4("<script>alert(1)</script>")
  2. 言语攻击

    譬如在聊天中输入"fuck, av, 国家领导人名字"等,策略是敏感词过滤
    先找到词库,作者用的部分词库在https://git.oschina.net/tywo45/t-io/tree/master/docs/dict,然后用https://www.oschina.net/p/hutool的com.xiaoleilu.hutool.dfa.WordTree来处理就好,具体用法请去hutool的官网。
  3. DDos攻击

    这个是作者没想到的,其实DDos攻击的性质还可以分成几个情况:
    • 单纯的技术玩耍(就是好玩,也不怀恶意,在快要攻击死对方后马上休手)
    • 单纯的技术破坏(攻击死对方后,自己在家偷着乐)
    • 恶意的技术破坏(譬如攻击后向受害者索要财物、或是攻击后散布谣言说随便刷新一下就把小站给弄死了)
    tio这个演示小站被攻击后,其实受损失的是为tio提供服务器的公司,他们为此额外买了一台新服务器,牢骚少发,否则红薯又要来教训我了,tio做了以下防范措施,可供大家参考
    • 记录所有访问交互动作,这个是相对容易做到的,也没什么技术含量,就不细说了,这一步主要是为了留下证据,万一构成刑事纠分,可能会有用。
    • 利用RateLimiter实现访问频率控制,不过作者在此基础上作了改造,下面可能会花点篇幅来介绍这个
      1. 对RateLimiter进一步封装,也没什么好说的,直接看代码吧,最核心的代码是Guava提供的RateLimiter
        package org.tio.monitor;
        
        import java.util.concurrent.atomic.AtomicInteger;
        
        import org.slf4j.Logger;
        import org.slf4j.LoggerFactory;
        import org.tio.core.utils.SystemTimer;
        
        import com.google.common.util.concurrent.RateLimiter;
        
        /**
         * @author tanyaowu 
         * 2017年5月23日 下午1:09:55
         */
        public class RateLimiterWrap {
        	private static Logger log = LoggerFactory.getLogger(RateLimiterWrap.class);
        
        	/**
        	 * 频率控制
        	 */
        	private RateLimiter rateLimiter = null;//RateLimiter.create(3);
        
        	/**
        	 * 本阶段已经收到多少次警告
        	 */
        	private AtomicInteger warnCount = new AtomicInteger();
        	
        	/**
        	 * 总共已经收到多少次警告
        	 */
        	private AtomicInteger allWarnCount = new AtomicInteger();
        
        	/**
        	 * 本阶段最多警告多次数
        	 */
        	private int maxWarnCount = 20;
        	
        	/**
        	 * 一共最多警告多次数
        	 */
        	private int maxAllWarnCount = maxWarnCount * 10;
        
        	/**
        	 * 上一次警告时间
        	 */
        	private long lastWarnTime = SystemTimer.currentTimeMillis();
        
        	/**
        	 * 警告清零时间间隔,即如果有这么长时间没有收到警告,则把前面的警告次数清零
        	 */
        	private int warnClearInterval = 1000 * 60 * 60 * 2;
        
        	/**
        	 * 
        	 * @param permitsPerSecond QPS
        	 * @param warnClearInterval 清理本阶段警告的时间间隔,参考值1000 * 60 * 60 * 2,单位为ms
        	 * @param maxWarnCount 本阶段最多警告多次数,参考值10
        	 * @param maxAllWarnCount 一共最多警告多次数
        	 * @author: tanyaowu
        	 */
        	public RateLimiterWrap(int permitsPerSecond, int warnClearInterval, int maxWarnCount, int maxAllWarnCount) {
        		this.rateLimiter = RateLimiter.create(permitsPerSecond);
        		this.warnClearInterval = warnClearInterval;
        		this.maxWarnCount = maxWarnCount;
        		this.maxAllWarnCount = maxAllWarnCount;
        	}
        
        	/**
        	 * 
        	 * @return 
        	 * 0位置:根据QPS获取执行锁, false: 没拿到锁<br>
        	 * 1位置:根据警告次数获取执行锁, false: 没拿到锁<br>
        	 * @author: tanyaowu
        	 */
        	public boolean[] tryAcquire() {
        		boolean ret = rateLimiter.tryAcquire();
        		if (!ret) {
        			synchronized (this) {
        				long nowTime = SystemTimer.currentTimeMillis();
        				if ((nowTime - lastWarnTime) > warnClearInterval) {
        					warnCount.set(0);
        				}
        				lastWarnTime = SystemTimer.currentTimeMillis();
        				int wc = warnCount.incrementAndGet();
        				int awc = allWarnCount.incrementAndGet();
        
        				if (wc > maxWarnCount || awc > maxAllWarnCount) {
        					return new boolean[]{false, false};
        				}
        				return new boolean[]{false, true};
        			}
        		} else {
        			return new boolean[]{true, true};
        		}
        
        	}
        ///其它非核心代码
        }

         

      2. 在消息处理入口处,用上前面这个东西即可
        ImSessionContext imSessionContext = channelContext.getSessionContext();
        RateLimiterWrap rateLimiterWrap = imSessionContext.getRequestRateLimiter();
        boolean[] ss = rateLimiterWrap.tryAcquire();
        String group = "g";
        if (ss[0] == false && ss[1] == false) {
        
        	log.error("{} 访问过频繁,本次命令:{}, 将拉黑其IP", channelContext.toString(), command);
        	//			String imgsrc = UserService.nextImg();
        	String text = "<span style='font-size:16px;'>对不起大家,由于我发消息太频繁,已经被服务器拉黑了,大家珍重</span>";
        	ChatRespBody.Builder builder = ChatRespBody.newBuilder();
        	builder.setType(ChatType.CHAT_TYPE_PUBLIC);
        	builder.setText(text);
        	builder.setFromClient(org.tio.examples.im.service.UserService.sysClient);
        
        	builder.setGroup(group);
        	builder.setTime(SystemTimer.currentTimeMillis());
        	ChatRespBody chatRespBody = builder.build();
        	ImPacket respPacket1 = new ImPacket(Command.COMMAND_CHAT_RESP, chatRespBody.toByteArray());
        	Aio.sendToGroup(groupContext, group, respPacket1);
        
        	Aio.IpBlacklist.add(groupContext, channelContext.getClientNode().getIp());
        	return null;
        } else if (ss[0] == false && ss[1] == true) {
        	log.error("{} 访问过频繁,本次命令:{},将警告一次", channelContext.toString(), command);
        
        	Client client = imSessionContext.getClient();
        	String nick = client.getUser().getNick();
        	String region = client.getRegion();
        	String ip = client.getIp();
        
        	int warnCount = rateLimiterWrap.getWarnCount().get();
        	int maxWarnCount = rateLimiterWrap.getMaxWarnCount();
        	int xx = maxWarnCount - warnCount;
        
        	String formatedUserAgent = ImUtils.formatUserAgent(channelContext);
        
        	String text = "<div class='tio-danger'>第" + warnCount + "次警告【" + nick + "】【" + region + "】【" + ip + "】【" + formatedUserAgent + "】,还剩" + xx + "次警告机会"
        			+ "</div>";
        	//				text += "<div style='font-size:14px;color:#ff0033'><a href='http://t-io.org:9292/ecosphere.html?v=4514545454' target='_blank'>如果被拉黑请联系作者, 欢迎对t-io生态圈进行投资建设,谢谢!</a></div>";
        	ChatRespBody.Builder builder = ChatRespBody.newBuilder();
        	builder.setType(ChatType.CHAT_TYPE_PUBLIC);
        	builder.setText(text);
        	builder.setFromClient(org.tio.examples.im.service.UserService.sysClient);
        
        	builder.setGroup(group);
        	builder.setTime(SystemTimer.currentTimeMillis());
        	ChatRespBody chatRespBody = builder.build();
        	ImPacket respPacket1 = new ImPacket(Command.COMMAND_CHAT_RESP, chatRespBody.toByteArray());
        	Aio.sendToGroup(groupContext, group, respPacket1);
        	return null;
        }
        }

         

  4. 其它方面的攻击

    作者也在慢慢积累各种经验,也希望大家是友好的攻防演练,而不要变成恶意攻击。

 

© 著作权归作者所有

共有 人打赏支持
talent-tan

talent-tan

粉丝 862
博文 34
码字总数 16087
作品 3
杭州
程序员
私信 提问
加载中

评论(14)

狮子追求真理
@talent-tan 看到您这个站点的配置是1g内存和1m带宽的,不知道有没有统计过可以同时在线多少人,最近也想在构建类似的个人站点,不知道该选用什么样的服务器合适
狮子追求真理
开源点赞
狮子追求真理
不知是否有什么交流群可供交流的
l
lblin

引用来自“花米”的评论

10秒,20秒,30秒内只能发言一次。这个限制应该比这个规则效率更高.

引用来自“talent-tan”的评论

一个是产品层面,一个是技术层面,我这个主要是技术玩耍和积累
请教下,您的tio到底是支持100W没有动作的连接还是支持100W同时聊天的连接+业务逻辑(发文字+同步文字到客户端)?
l
lblin

引用来自“花米”的评论

10秒,20秒,30秒内只能发言一次。这个限制应该比这个规则效率更高.
体验差
talent-tan
talent-tan

引用来自“花米”的评论

10秒,20秒,30秒内只能发言一次。这个限制应该比这个规则效率更高.
一个是产品层面,一个是技术层面,我这个主要是技术玩耍和积累
花米
花米
10秒,20秒,30秒内只能发言一次。这个限制应该比这个规则效率更高.
路小磊
路小磊

引用来自“talent-tan”的评论

引用来自“路小磊”的评论

RateLimiter看起来好棒,我要学习下:grin:
RateLimiter还不是太灵活,你要不要按照文中的套路加强一把?

先吃透原理再说,嘿嘿
talent-tan
talent-tan

引用来自“路小磊”的评论

RateLimiter看起来好棒,我要学习下:grin:
RateLimiter还不是太灵活,你要不要按照文中的套路加强一把?
路小磊
路小磊
RateLimiter看起来好棒,我要学习下:grin:
t-io 1.7.1 发布:不仅仅是百万级 TCP 长连接框架

t-io 目标提升 不仅仅是百万级TCP长连接框架,这是t-io的第三个目标了,前两个都已实现。 目标先定下来,逐步实现,当年吹过的牛,大都含着泪完成了 要往短连接方面扩展 支持更多的传输层协议...

talent-tan
2017/07/03
6.1K
67
、轨迹/tio-im

tio-im简介 tio-im是基于t-io写的IM,主要目标降低即时通讯门槛,通过极简洁的消息格式就可以实现多端不同协议间的消息发送如(http、websocket、tcp自定义im协议)等,并可以通过http协议的a...

、轨迹
2017/08/31
0
0
t-io 3.2.0 发布:王谢堂前燕,飞入寻常百姓家

t-io简介 t-io 是基于aio(nio2)的网络编程框架,和netty属于同类,但t-io更注重开发一线工程师的感受,提供了大量和业务相关的API。基于t-io来开发IM、TCP私有协议、RPC、游戏服务器端、推送...

talent-tan
09/14
0
0
t-io 3.1.9 发布,王谢堂前燕,飞入寻常码农家

t-io简介 t-io 是基于aio(nio2)的网络编程框架,和netty属于同类,但t-io更注重开发一线工程师的感受,提供了大量和业务相关的API。基于t-io来开发IM、TCP私有协议、RPC、游戏服务器端、推送...

talent-tan
08/30
0
0
支持百万在线用户IM - J-IM

J-IM简介 J-IM(原名tio-im)是基于t-io写的轻量、高性能、(可能)支持百万在线用户IM,主要目标降低即时通讯门槛,快速打造低成本接入在线IM系统,通过极简洁的消息格式就可以实现多端不同协议...

轨迹_
05/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

以太坊Token通证或者代币的真正作用是什么?

上一篇文章以太坊(Ethereum)与以太(Ether)中,你应该很好地理解以太坊是如何构建以太坊应用程序网络的,这些应用程序需要一个名为Ether的加密货币来运行。现在是时候引入一个更深层的概念...

笔阁
30分钟前
3
0
PHP - 利用P3P实现跨域

P3P是什么 P3P Platform for Privacy Preferences, 是W3C公布的一项隐私保护推荐标准,以为用户提供隐私保护。 P3P标准的构想是:Web 站点的隐私策略应该告之访问者该站点所收集的信息类型、...

hansonwong
31分钟前
2
0
传统SSM框架之微信授权登陆

1、jdbc.properties (下面瞎写的值) WEIXIN_APP_ID=wx5438496a99c8d26acbWEIXIN_APP_SECRET=d070fjcwiefhwr38942dw 2、获取配置属性 /** * @Author:Mujiutian * @Description:微信参......

木九天
31分钟前
3
0
以太坊(Ethereum)与以太(Ether)为什么容易混淆?

客观的来说,以太坊与以太这两个概念很容易混淆。 当我们听到以太坊Ethereum这个词时,我们通常会将它与加密货币(比如比特币)联系起来。虽然这个定义并不完全错误。但重要的是要理解以太坊...

geek12345
33分钟前
2
0
ROS实操笔记四 msg 和srv

msg: msg files are simple text files that describe the fields of a ROS message. They are used to generate source code for messages in different languages. srv: an srv file descr......

placido
34分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部