文档章节

t-io im小站攻防实录

talent-tan
 talent-tan
发布于 2017/06/01 10:37
字数 1166
阅读 3400
收藏 31
点赞 9
评论 14

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

粉丝 734
博文 23
码字总数 11857
作品 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 ⋅ 67

、轨迹/tio-im

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

、轨迹 ⋅ 2017/08/31 ⋅ 0

支持百万在线用户IM - J-IM

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

轨迹_ ⋅ 05/07 ⋅ 0

t-io 2.4.0 发布, 不仅仅是百万级 TCP 长连接框架

修改点: 1、AioHandler.decode(ByteBuffer buffer, ChannelContext channelContext)方法签名改成AioHandler.decode(ByteBuffer buffer, int limit, int position, int readableLength, Cha......

talent-tan ⋅ 05/07 ⋅ 0

图形系统中的仿射变换

终于建了一个自己个人小站:https://huangtianyu.gitee.io,以后优先更新小站博客,欢迎进站,O(∩_∩)O~~ 在学图形学的时候,仿射变换肯定会遇到,那到底什么是仿射变换了?在做仿射变换时一...

乾初 ⋅ 02/07 ⋅ 0

J-IM v2.1.0 发布,支持 SSL/TLS 安全加密传输

J-IM 2.1.0 发布了,J-IM 是用 JAVA 语言,基 于t-io 开发的轻量、高性能、支持几十万至百万在线用户的IM(即时通讯)框架,它的主要目标降低即时通讯门槛,使用者基于它可以极快速、低成本的打造...

轨迹_ ⋅ 06/11 ⋅ 0

t-io 2.0.0 发布 —— 法网天眼第一版

talent-tan ⋅ 2017/08/24 ⋅ 59

J-IM 1.1.0、2.0.1 发布 紧急修复TCP协议解码BUG

J-IM 1.1.0、2.0.1 发布了,J-IM 是一个用 JAVA 语言,基 于t-io 开发的轻量、高性能、支持几十万至百万在线用户的IM(即时通讯)框架,它的主要目标降低即时通讯门槛,使用者基于它可以极快速、...

轨迹_ ⋅ 06/04 ⋅ 0

t-io关于使用websocket的问题

@talent-tan 你好,想跟你请教个问题: 我才刚刚接触t-io,是个技术小白 我仿照t-io的demo中的tio-examples-im-simple-的例子写了一个关于websocket的例子,但是运行的程序总是报错,发送不了...

dclsmile ⋅ 2017/05/23 ⋅ 3

centos6安装docker

使用的操作系统是是centos6.3,按照官方的推荐的配置,把linux内核升级到3.8以上。 安装步骤如下: 1、升级内核版本(包含aufs) cd /etc/yum.repos.d wget http://www.hop5.in/yum/el6/hop5...

黎晨 ⋅ 2017/06/26 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

博客迁移到 https://www.jianshu.com/u/aa501451a235

博客迁移到 https://www.jianshu.com/u/aa501451a235 本博客不再更新

为为02 ⋅ 35分钟前 ⋅ 0

win10怎么彻底关闭自动更新

win10自带的更新每天都很多,每一次下载都要占用大量网络,而且安装要等得时间也蛮久的。 工具/原料 Win10 方法/步骤 单击左下角开始菜单点击设置图标进入设置界面 在设置窗口中输入“服务”...

阿K1225 ⋅ 今天 ⋅ 0

Elasticsearch 6.3.0 SQL功能使用案例分享

The best elasticsearch highlevel java rest api-----bboss Elasticsearch 6.3.0 官方新推出的SQL检索插件非常不错,本文一个实际案例来介绍其使用方法。 1.代码中的sql检索 @Testpu...

bboss ⋅ 今天 ⋅ 0

informix数据库在linux中的安装以及用java/c/c++访问

一、安装前准备 安装JDK(略) 到IBM官网上下载informix软件:iif.12.10.FC9DE.linux-x86_64.tar放在某个大家都可以访问的目录比如:/mypkg,并解压到该目录下。 我也放到了百度云和天翼云上...

wangxuwei ⋅ 今天 ⋅ 0

PHP语言系统ZBLOG或许无法重现月光博客的闪耀历史[图]

最近在写博客,希望通过自己努力打造一个优秀的教育类主题博客,名动江湖,但是问题来了,现在写博客还有前途吗?面对强大的自媒体站点围剿,还有信心和可能型吗? 至于程序部分,我选择了P...

原创小博客 ⋅ 今天 ⋅ 0

IntelliJ IDEA 2018.1新特性

工欲善其事必先利其器,如果有一款IDE可以让你更高效地专注于开发以及源码阅读,为什么不试一试? 本文转载自:netty技术内幕 3月27日,jetbrains正式发布期待已久的IntelliJ IDEA 2018.1,再...

Romane ⋅ 今天 ⋅ 0

浅谈设计模式之工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻...

佛系程序猿灬 ⋅ 今天 ⋅ 0

Dockerfile基础命令总结

FROM 指定使用的基础base image FROM scratch # 制作base image ,不使用任何基础imageFROM centos # 使用base imageFROM ubuntu:14.04 尽量使用官方的base image,为了安全 LABEL 描述作...

ExtreU ⋅ 昨天 ⋅ 0

存储,对比私有云和公有云的不同

导读 说起公共存储,很难不与后网络公司时代的选择性外包联系起来,但尽管如此,它还是具备着简单和固有的可用性。公共存储的名字听起来也缺乏专有性,很像是把东西直接堆放在那里而不会得到...

问题终结者 ⋅ 昨天 ⋅ 0

C++难点解析之const修饰符

C++难点解析之const修饰符 c++ 相比于其他编程语言,可能是最为难掌握,概念最为复杂的。结合自己平时的C++使用经验,这里将会列举出一些常见的难点并给出相应的解释。 const修饰符 const在c...

jackie8tao ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部