wtf! Redis Crackit,我被黑了 =。=#

先前学redis时候是放在亚马逊的云主机上部署的redis-server,因为亚马逊云的默认安全策略是禁止所有端口的外网访问,要想从外网访问云主机,必须手动在安全策略开启所需端口,这能有效防止无意识的端口暴露。而阿里云的默认安全策略则是允许所有端口的外网访问权限,简直日了狗了,以前从没注意过。 昨天想着要重构下我的betspider爬虫,将一些实时数据放到redis缓存中,所以在阿里云也开了redis-server。redis的默认配置是允许所有远程连接,并且无需密码。 这种情况下:阿里云无安全策略,所有端口暴露给外网;redis-server无需密码登陆、允许远程连接。那么就相当于将我的redis-server暴露在所有人面前,谁都可以访问到。活生生的Redis Crackit肉鸡。 Redis Crackit漏洞: 黑客远程访问redis服务,清空redis数据库后写入他自己的ssh登录公钥,然后将redis数据库备份为/root/.ssh/authotrized_keys。 这就成功地将自己的公钥写入到ssh的authotrized_keys,无需密码直接root登录被黑的主机。大写的SAD.   事情的经过是这样的,应该是今天中午的时候吧大概,正好用phpRedisAdmin查看我的redis-server,发现里面有一个很陌生的key,值为“ssh-ras xxxx”一大串字符串,当时我还没反应过来这是什么玩意,就奇怪了一下怎么莫名其妙多了一个key,然后随手就把他删除了,这个时候,应该就是黑客正在作案的时候,还真巧=。=# 后来,再登录的时候,发下root目录下多了一个奇怪的脚本get.sh,内容是下载xx程序后台执行,然后删除程序文件。想了一会觉得特别不对劲,卧槽难道我被黑了,赶紧history检查历史命令,发现没有什么异常,估计这时候history记录已经被黑客清理干净了,但却忘删get.sh这个脚本文件了。 后来正好看手机短信,发现有条未读的阿里云短信,说我的服务器在荷兰(89.248.162.167)处登录,可能是黑客入侵。what the hell,我居然现在才看到短信!!! 当时想了好一会儿,卧槽怎么回事,怎么会被黑了,赶紧改密码,日了狗了。到底怎么回事。咦,我的redis好像没有做访问控制,可以被所有人访问到呀,是不是redis有漏洞?赶紧百度一下,what the fuck!果然是redis的漏洞,靠!赶紧停redis-server。 处理方法: 修改redis配置文件,打开被注释的bind […]

docker入门 – 使用docker在单机上搭建redis集群

昨天玩了一下docker,感觉官方Get Started教程里面那个whalesay的例子实在是太渣,没有一点实际用途。解释了image跟container的关系,但完全没有体现container与本地进程的关系。 在实际应用场景上,我感觉docker应该更经常会用在部署nginx、memcache这些无需持久化到本地文件的服务进程上面,一个container就相当于一个进程,随用随起,而且不受本机环境限制。docker应该还可以用在Online Judge这样的在线编程系统上,不用再担心恶意代码搞坏本机系统了。不知道Quantopian这些在线交易策略的后台是不是也用docker给每个用户一个container来跑他们的策略,有点意思嘿嘿。另外docker用来做测试环境也特方便,比如本文要做的redis集群,实际应用肯定是将每个redis-server部署在不同的服务器上,穷酸点的可以部署在不同虚拟机上,但用docker可以很方便的在一台机器起好几个redis-server进程。 1. 下载安装docker 2. 直接去docker hub拉取redis官方镜像 # docker pull redis 使用docker images可以列出当前所有的docker镜像。 docker镜像与容器的实际存储目录一般都在/var/lib/docker下面,关于docker的底层存储结构,这个应该得花大时间才能有所心得了。 3. 从redis镜像启动一个容器 # docker

小内存运行kafka

按照kafka的官方文档(http://kafka.apache.org/documentation.html#quickstart)试了一下,解压程序包后运行 $bin/zookeeper-server-start.sh config/zookeeper.properties &   结果一上来就报错,无法分配内存。 从错误输出来看,这个zookeeper-server要求申请536870912字节(512MB)内存 =。=#。。 日了狗了我的亚马逊主机总共才1GB物理内存而且还没建swap分区,free看了一下大概就剩200MB左右的可用内存。检查这个命令的两个文件,发现在zookeeper-server-start.sh中有个定义export KAFKA_HEAP_OPTS=”-Xmx512M -Xms512M”。上来就要jvm去申请512MB的最小空间,把这个Xms改成16M后zookeeper就启动正常了。 然后做下一步启动kafka-esrver $bin/kafka-server-start.sh config/server.properties & 同样遇到这个问题,修改kafka-server-start.sh中的Xms配置(这个更狠,要了1GB的初始内存) 重新启动kafka-server,这回又显示如下错误:OutOfMemoryError 这回是jvm已经启动,在kafka的程序内部分配内存时候出错了。看来除了在启动jvm前就申请了大内存,在kafka程序内部又申请了大内存。 先去检查作为启动参数的server.properties文件,里面关于size的配置都不大,不至于OutOfMemory。 再检查kafka的源码,定位到KafkaServer.scala的589行附近。

Spring的@Autowired与自动代理

我想Spring框架的优点,第一条应该就是Spring的依赖注入了吧。尤其@Autowired这个注解,甚至可以直接注解在私有成员变量上而不用去写setter方法。之前看《Spring实战》这书的时候,里面说autowired自动注入是byType的,当时一直以为就是byClass,就是根据变量的类类型,去Spring context中找这样类型的bean。但当我写Dao层、Service层代码的时候,发现情况根本不是这样的。 比如说我现有有一个BookmakerDao接口,以及接口的实现类BookmakerDaoHibernate,并用@Repository注解将实现类注解为Spring bean。 public interface BookmakerDao { /** * */ } @Repository public class BookmakerDaoHibernate implements BookmakerDao { /**

Entity的继承以及泛型Dao(二)

一、继承与泛型都是因为懒 接着先前的例子,我们已经把Odds1x2与OddsHandicap这两个实体类的共同属性抽离出来放在他们的抽象父类Odds中。那么接下来要做的就是实现实体类相应的Dao类型。最简单的实现方法就是每个Entity对应一个Dao,每个Dao内都要实现对Entity的增删查改操作,但实际上大部分的增删查改操作都是类似的,只是处理不同的Entity而已。为了少写些重复代码,我们有完全正当的理由写一个泛型Dao来实现这些基本的增删查改操作。 仍然以我们的Odds为例子,假设我们现在只需要实现一个功能,就是查找某场比赛的某种赔率。 public interface OddsDao <T> { /** * 获取所有与某场赛事相关的有效赔率 * @param matchId * @return */ List<T> getAllValidByMatchId(long matchId);

Entity的继承以及泛型Dao(一)

一、两张类似的表与两个类似的实体类 现在我有一个betspider数据库,里面放着我自己的爬虫爬来的足球赔率,以bs_odds_1x2(胜负平赔率)、bs_odds_handicap(让球赔率)这两张表作为例子,他们在数据库中的表结构是这样的: 首先不考虑实体类的继承,这两张表对应着两个独立的实体类:(请暂时忽略下面实体类属性的数据类型与mysql的表字段类型的不完全匹配 =。=#) @Entity @Table(name = "bs_odds_1x2") public class Odds1x2 implements Serializable { private static final long serialVersionUID =

freemarker实现通用布局的模板拆分与复用

一、基础页面布局 假设我们项目页面的通用布局如下图所示: 实现这样的布局的基本html代码如下: <html> <head> </head> <body> <div style="width: 700px; text-align:center; font-size:30px;"> <div style="background-color: #b4efb8;">header</div> <div style="width:30%; height:300px; float:left; background-color:

Spring中@ModelAttribute以及超级坑爹的@SessionAttributes注解

重要的结论要先说出来,千万不要用@SessionAttributes来保存http session的属性!!! 在Spring MVC中,@ModelAttribute注解作用在方法或者方法参数上,表示将被注解的方法的返回值或者是被注解的参数作为Model的属性加入到Model中,然后Spring框架自会将这个Model传递给ViewResolver。Model的生命周期只有一个http请求的处理过程,请求处理完后,Model就销毁了。 @SessionAttributes(attrName)注解的意思就是将Model中的attrName属性作为session的属性保存下来。 但关键是它并不仅仅是将这个属性放到HttpSession中这么简单!它的做法大概可以理解为将Model中的被注解的attrName属性保存在一个SessionAttributesHandler中,在每个RequestMapping的方法执行后,这个SessionAttributesHandler都会将它自己管理的“属性”从Model中写入到真正的HttpSession;同样,在每个RequestMapping的方法执行前,SessionAttributesHandler会将HttpSession中的被@SessionAttributes注解的属性写入到新的Model中。注意!它的生命周期很别扭哦! 所以如果在方法中用HttpSession.removeAttribute()来删除被@SessionAttributes注解的属性,你会发现根本没有效果,因为方法执行结束后,它又被SessionAttributesHandler从Model中写回HttpSession了。可以用一个SessionStatus.setComplete()方法来让SessionAttributesHandler在方法结束后不接手工作,从而达到不写入HttpSession的目的,但这方法太鸡巴扯了我感觉。 所以,最重要的是,千万不要使用@SessionAttributes注解来管理session的属性!!! 下面贴一个简单的例子,自己试一下就知道了 /** * 被@SessionAttributes注解的类,会有一个SessionAttributesHandler加入它的HandlerExecutionChain中 * 在每个RequestMapping的方法执行前,SessionAttributesHandler都会将testSession从HttpSession写入Model * 在每个RequestMapping的方法执行后,SessionAttributesHandler都会将testSession从Model写入HttpSession */ @Controller @RequestMapping("/test") @SessionAttributes("testSession")

文件系统使用率du、df二者相差过大的问题

今天在单位遇到一个问题,有一台服务器文件系统的磁盘使用率超过80%,因此打算清理一下没用的文件。 使用df检查发现/home目录占用了105G,而用du命令检查/home目录只占用了64G,整整差了41G!即使df与du命令的检查结果是可能会存在些许不同,但相差了这么多,明显是有问题了。通常导致这个问题的原因,当一个文件被删除后,在目录中已经不可见了,所以du就不会再统计它了。然而如果此时还有进程持有这个已经被删除了的文件的句柄,那么这个文件就不会真正在磁盘中被删除,这样df仍旧会统计这个被删除了的文件。 我们可以使用lsof命令(list open files)来检查被打开的文件,并grep下是否已经deleted(很不幸,检测是否deleted这个,并不是所有系统的lsof都支持的,我的mac就不会。 那样的话只能自己写个脚本一个一个文件去检查是否还在目录中了) 检查结果如上图,这两个pid为8363、8364的jsvc进程打开了已经被删除的日志文件catalina.out.8,而且这个文件有40G之大! =。=#  我怀疑是这个系统的开发人员以为写个定时任务删除了过期日志文件就好了,结果在程序中又没有关闭这个文件句柄,还接着往这个文件里面倒数据。。。 解决办法一是重启对应的进程,释放该文件句柄;二是使用命令清空文件$cat /dev/null > filename。

在spring中使用hibernate

一、基本配置 在Spring的servlet-context.xml文件中添加 <!– 配置数据库 –> <!– 简单的使用jdbc的DriverManagerDataSource,没有连接池 –> <beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <beans:property name="driverClassName" value="com.mysql.jdbc.Driver" /> <beans:property name="url" value="jdbc:mysql://localhost:3306/your_database" /> <beans:property

Scroll to Top