[转] 让Docker功能更强大的10个开源工具

2016-10-18 09:12:31 查看评论 250 人阅读    

软件项目的成功常常根据其催生的生态系统来衡量。围绕或基于核心技术构建的项目增添了功能和易用性,它们常常日臻完善。Docker就是一个典例,这个软件容器化系统让IT部门可以专注于应用程序、而不是虚拟机,作为生产的标准单位。

Docker一向备受第一方和第三方开发人员的关注,而众多项目扩展、补充或改进Docker,却没有成为Docker的一部分。下面是如今正在开发中的10个最知名的项目,从长远来看,有些项目有机会成为Docker的一部分。

分类: Linux 标签: docker

Linux服务器上查杀木马经历

2016-08-03 14:52:54 查看评论 675 人阅读    

收到VPS服务商的邮件,警告说我的VPS服务器的负载过高,已经被暂时关闭了,让我赶快处理解决。

Suspend Reason: High Load Avg - 23.13 / 23.17 / 23.16

很是诧异,这个VPS就放了一个博客和两个小站点,平时也没啥访问,怎么会导致负载高呢。

解决过程

急忙登陆上了vps,发现连接特别慢,马上top查看下,输入P进行按照CPU排序。

多了个CPU占用特别高的陌生程序minerd,明显是被挂马了,网上搜索了下,发现这个是个挖矿程序,被攻击了。

分类: Linux 标签: linux 攻击 minerd 木马

WEB/APP开发安全

2016-04-26 14:39:10 查看评论 719 人阅读    

最近公司被攻击了,然后才发现公司代码简直一点安全防范意识都没有,连基本的SQL,XSS过滤都没有,发现大部分PHP程序员都缺乏安全相关的了解。下面就我们遇到的一些攻击进行科普以及防范方案。

SQL注入

SQL注入是WEB攻击中最常见的注入方式。也是我们这次被攻击中最多的。
由于我们的程序中大部分都是进行拼装SQL的方式,然后对于用户输入的参数也没有进行过滤,导致给攻击者留下了漏洞。
具体为,登录的操作,一般是通过POST方式将username和password传递过来。

SELECT * FROM user WHERE username='$username' AND password='$password'


正常情况下,我们希望执行的SQL是

SELECT * FROM user WHERE username='vckai' AND password='123456'


但是如果攻击者传递的用户为非法用户名vckai' or 1=1--,在SQL里面—是注释标记,所以查询语句会在此中断。这就让攻击者在不知道任何合法用户名和密码的情况下成功登录了。

SELECT * FROM user WHERE username='vckai' or 1=1--' AND password='123456'


甚至于,攻击者可以用同样的方式执行其他SQL,查询出你其他DB和表数据。

现在知道SQL注入的危害了,那怎么预防呢?

  • 首先在PHP中,首先对于int类型的数据,一定要在接收数据的时候进行(int) $_POST['pagesize']进行强转义。

  • 根据业务做参数验证,如用户名一般只允许4-20位字符和数字。这样攻击者就没办法根据这个进行注入了。

  • 虽然MySQL和PHP本身由提供过滤函数addslashesmysql_real_escape_string进行转义,但是仍然有被绕过的风险,所以最佳方法是使用PDO的预处理。详情见:使用PDO防止SQL注入

[转] 浅谈PHP弱类型安全

2016-04-20 21:27:57 查看评论 409 人阅读    

0x00 弱类型初探


没有人质疑php的简单强大,它提供了很多特性供开发者使用,其中一个就是弱类型机制。

在弱类型机制下 你能够执行这样的操作

1
2
3
4
5
<?php
$var = 1;
$var = array();
$var = "string";
?>

php不会严格检验传入的变量类型,也可以将变量自由的转换类型。

比如 在$a == $b的比较中

  • $a = null; $b = false; //为真

  • $a = ''; $b = 0; //同样为真

然而,php内核的开发者原本是想让程序员借由这种不需要声明的体系,更加高效的开发,所以在几乎所有内置函数以及基本结构中使用了很多松散的比较和转换,防止程序中的变量因为程序员的不规范而频繁的报错,然而这却带来了安全问题。

分类: PHP 标签: 弱类型 安全

[转] PHP中用PDO查询MySQL避免SQL注入示例和应注意的地方

2016-04-20 20:24:01 查看评论 783 人阅读    

当我们使用传统的 mysql_connect 、mysql_query方法来连接查询数据库时,如果过滤不严,就有SQL注入风险,导致网站被攻击,失去控制。虽然可以用mysql_real_escape_string()函数过滤用户提交的值,但是也有缺陷。(注:请弃用mysql_escape_string,php5.5已经废弃,php7已经移除。

mysql_real_escape_stringaddslashes的区别

区别一

addslashes不知道任何有关MySQL连接的字符集。
如果你给所使用的MySQL连接传递一个包含字节编码之外的其他编码的字符串,
它会很愉快地把所有值为字符'、"、\和\x00的字节进行转义。
如果你正在使用不同于8位和UTF-8的其它字符,
这些字节的值不一定全部都是表示字符'、"、\和\x00。可能造成的结果是,MySQL接收这些字符后出现错误。
如果要修正这个bug,可尝试使用iconv函数,将变量转为UTF-16,然后再使用addslashes进行转义。

 区别二

与addslashes对比,mysql_real_escape_string同时还对\r、\n和\x1a进行转义。看来,这些字符必须正确地告诉MySQL,否则会得到错误的查询结果

在GBK里,0xbf27不是一个合法的多字符字符,但0xbf5c却是。在单字节环境里,0xbf27被视为0xbf后面跟着0x27('),同时0xbf5c被视为0xbf后面跟着0x5c(\)。

一个用反斜杠转义的单引号,是无法有效阻止针对MySQL的SQL注入攻击的。
如果你使用addslashes,那么,我(攻击者,下同)是很幸运的。
我只要注入一些类似0xbf27,然后addslashes将它修改为0xbf5c27,一个合法的多字节字符后面接着一个单引号。
换句话说,我可以无视你的转义,成功地注入一个单引号。这是因为0xbf5c被当作单字节字符,而非双字节。

所以不管转义,针对针对php 5.3.6以前版本,这套方法还是可以找到漏洞的。而使用PHP的PDO扩展的 prepare 方法,就可以避免sql injection 风险。

PDO(PHP Data Object) 是PHP5新加入的一个重大功能,因为在PHP 5以前的php4/php3都是一堆的数据库扩展来跟各个数据库的连接和处理,如 php_mysql.dll。 PHP6中也将默认使用PDO的方式连接,mysql扩展将被作为辅助 。官方:http://php.net/manual/en/book.pdo.php


分类: PHP 标签: pdo sql注入

[转]手把手教你用Strace诊断问题

2016-04-07 17:22:44 查看评论 392 人阅读    

早些年,如果你知道有个 strace 命令,就很牛了,而现在大家基本都知道 strace 了,如果你遇到性能问题求助别人,十有八九会建议你用 strace 挂上去看看,不过当你挂上去了,看着满屏翻滚的字符,却十有八九看不出个所以然。本文通过一个简单的案例,向你展示一下在用 strace 诊断问题时的一些套路。

如下真实案例,如有雷同,实属必然!让我们看一台高负载服务器的 top 结果:

top

top

技巧:运行 top 时,按「1」打开 CPU 列表,按「shift+p」以 CPU 排序。

在本例中大家很容易发现 CPU 主要是被若干个 PHP 进程占用了,同时 PHP 进程占用的比较多的内存,不过系统内存尚有结余,SWAP 也不严重,这并不是问题主因。

分类: Linux 标签: strace

使用GDB调试PHP core dump

2016-03-30 12:20:27 查看评论 1245 人阅读    

最近线上服务器出现了访问不上的情况,查看php-fpm发现大量的WARNING: [pool www] child 11274 exited on signal 31 (SIGSYS) after 0.089068 seconds from start错误,然后php-fpm进程在不断的重启。

查看PHP的错误日记并没有太多可用信息,既然如此那就尝试抓取core dump使用gdb调试看下吧。


关于core dump

我们经常听到大家说到程序core掉了,需要定位解决,这里说的大部分是指对应程序由于各种异常或者bug导致在运行过程中异常退出或者中止,并且在满足一定条件下(这里为什么说需要满足一定的条件呢?下面会分析)会产生一个叫做core的文件。

        通常情况下,core文件会包含了程序运行时的内存,寄存器状态,堆栈指针,内存管理信息还有各种函数调用堆栈信息等,我们可以理解为是程序工作当前状态存储生成第一个文件,许多的程序出错的时候都会产生一个core文件,通过工具分析这个文件,我们可以定位到程序异常退出的时候对应的堆栈调用等信息,找出问题所在并进行及时解决。


core dump默认是不生成的文件,所以首先我们要开启下。

分类: PHP 标签: php core dump gdb

关于订单号的生成

2015-08-14 13:03:02 查看评论 1092 人阅读    

最近面试某公司的时候被问到这个,一开始想法是以流水叠加的方式,借助redis的incr生成一个流水订单号,可以增加前缀。如:2015081400001,后面五位数进行递增。


面试官:如果不想让别人根据订单号来统计流水呢。

这时候第一想法是每日定时生成一批订单,然后存放在redis/mysql,使用的时候进行获取即可。但是仍然无法解决随机获取的问题,随机key的话又要考虑互斥问题。所以想到使用incr的进行random 1-5之间的递增。然后以index去获取order id。


面试官:如果要保证这批订单号都能使用上呢。

对于最后的这个问题当时并没有答得出来。

之后问了下面试官,答题是跟我的思路类似,也是使用incr做index,当时没有想明白。因为按照好我的方式话保证不了随机获取,而且所有的订单号都能获取到。

==================================================================================================

晚上回来之后突然想到,其实思路没问题的,只是纠结在存在redis/mysql是顺序生成的订单号,所以获取的时候也只能顺序获取。mysql倒是有rand()函数,但是性能不好,而且会导致索引失效。 但其实可以生成订单号的时候程序可以进行打乱这批订单号再存储!这样就可以解决这个问题了。

直接上代码

<?php
// 每日生成的最大订单流水号, 可以根据实际应用进行调整
define('NUM', 1000);

// 链接redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$order = null;
$pre = date('Ymd');

// 生成订单流水数组
$arr = range(0, NUM);

// 数组乱序
shuffle($arr);

$redis->delete('order');

// 插入订单号进入redis
foreach ($arr as $i) {
    $order = $pre . str_pad($i, 5, 0, STR_PAD_LEFT);
    $redis->rPush('order', $order);
}


// 获取订单号
$orders = [];
for($i = 0; $i < 10000; $i++) {
    $orders[] = $redis->lPop('order');
}
var_dump($orders);



分类: 随笔 标签: 订单号生成

[转]分布式Redis架构设计和踩过的那些坑们

2015-07-12 08:12:13 查看评论 1451 人阅读    

此文根据【QCON高可用架构群】分享内容,由群内【编辑组】志愿整理,转发请注明出处。

      黄东旭,Ping CAP CTO,开源项目Codis的co-author。之前在豌豆荚从事infrastructure相关的工作,现在在创业公司PingCAP,方向依然是分布式存储领域(NewSQL)。


本次分享的内容主要包括五个大部分:

  • Redis、RedisCluster和Codis;

  • 我们更爱一致性;

  • Codis在生产环境中的使用的经验和坑们;

  • 对于分布式数据库和分布式架构的一些看法;

  • Q & A环节。

  Codis是一个分布式Redis解决方案,与官方的纯P2P的模式不同,Codis采用的是Proxy-based的方案。今天我们介绍一下Codis及下一个大版本RebornDB的设计,同时会介绍一些Codis在实际应用场景中的tips。最后抛砖引玉,会介绍一下我对分布式存储的一些观点和看法,望各位首席们雅正。

一、 Redis,RedisCluster和Codis


  Redis:想必大家的架构中,Redis已经是一个必不可少的部件,丰富的数据结构和超高的性能以及简单的协议,让Redis能够很好的作为数据库的上游缓存层。但是我们会比较担心Redis的单点问题,单点Redis容量大小总受限于内存,在业务对性能要求比较高的情况下,理想情况下我们希望所有的数据都能在内存里面,不要打到数据库上,所以很自然的就会寻求其他方案。 比如,SSD将内存换成了磁盘,以换取更大的容量。更自然的想法是将Redis变成一个可以水平扩展的分布式缓存服务,在Codis之前,业界只有Twemproxy,但是Twemproxy本身是一个静态的分布式Redis方案,进行扩容/缩容时候对运维要求非常高,而且很难做到平滑的扩缩容。Codis的目标其实就是尽量兼容Twemproxy的基础上,加上数据迁移的功能以实现扩容和缩容,最终替换Twemproxy。从豌豆荚最后上线的结果来看,最后完全替换了Twem,大概2T左右的内存集群。

  Redis Cluster  :与Codis同期发布正式版的官方cluster,我认为有优点也有缺点,作为架构师,我并不会在生产环境中使用,原因有两个:

  • cluster的数据存储模块和分布式的逻辑模块是耦合在一起的,这个带来的好处是部署异常简单,all-in-the-box,没有像Codis那么多概念,组件和依赖。但是带来的缺点是,你很难对业务进行无痛的升级。比如哪天Redis cluster的分布式逻辑出现了比较严重的bug,你该如何升级?除了滚动重启整个集群,没什么好办法。这个比较伤运维。

  • 对协议进行了较大的修改,对客户端不太友好,目前很多客户端已经成为事实标准,而且很多程序已经写好了,让业务方去更换Redisclient,是不太现实的,而且目前很难说有哪个Rediscluster客户端经过了大规模生产环境的验证,从HunanTV开源的Rediscluster proxy上可以看得出这个影响还是蛮大的,否则就会支持使用cluster的client了。

  Codis:和Redis cluster不同的是,Codis采用一层无状态的proxy层,将分布式逻辑写在proxy上,底层的存储引擎还是Redis本身(尽管基于Redis2.8.13上做了一些小patch),数据的分布状态存储于zookeeper(etcd)中,底层的数据存储变成了可插拔的部件。这个事情的好处其实不用多说,就是各个部件是可以动态水平扩展的,尤其无状态的proxy对于动态的负载均衡,还是意义很大的,而且还可以做一些有意思的事情,比如发现一些slot的数据比较冷,可以专门用一个支持持久化存储的server group来负责这部分slot,以节省内存,当这部分数据变热起来时,可以再动态的迁移到内存的server group上,一切对业务透明。比较有意思的是,在Twitter内部弃用Twmeproxy后,t家自己开发了一个新的分布式Redis解决方案,仍然走的是proxy-based路线。不过没有开源出来。可插拔存储引擎这个事情也是Codis的下一代产品RebornDB在做的一件事情。btw,RebornDB和它的持久化引擎都是完全开源的,见https://github.com/reborndb/reborn和https://github.com/reborndb/qdb。当然这样的设计的坏处是,经过了proxy,多了一次网络交互,看上去性能下降了一些,但是记住,我们的proxy是可以动态扩展的,整个服务的QPS并不由单个proxy的性能决定(所以生产环境中我建议使用LVS/HA Proxy或者Jodis),每个proxy其实都是一样的。

640.png


分类: Nosql 标签: codis redis 分布式

[转]MySQL索引原理及慢查询优化

2015-05-20 08:50:37 查看评论 702 人阅读    

MySQL凭借着出色的性能、低廉的成本、丰富的资源,已经成为绝大多数互联网公司的首选关系型数据库。虽然性能出色,但所谓“好马配好鞍”,如何能够更好的使用它,已经成为开发工程师的必修课,我们经常会从职位描述上看到诸如“精通MySQL”、“SQL语句优化”、“了解数据库原理”等要求。我们知道一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,所以查询语句的优化显然是重中之重。
本人从13年7月份起,一直在美团核心业务系统部做慢查询的优化工作,共计十余个系统,累计解决和积累了上百个慢查询案例。随着业务的复杂性提升,遇到的问题千奇百怪,五花八门,匪夷所思。本文旨在以开发工程师的角度来解释数据库索引的原理和如何优化慢查询。

一个慢查询引发的思考

select
   count(*) 
from
   task 
where
   status=2 
   and operator_id=20839 
   and operate_time>1371169729 
   and operate_time<1371174603 
   and type=2;

系统使用者反应有一个功能越来越慢,于是工程师找到了上面的SQL。
并且兴致冲冲的找到了我,“这个SQL需要优化,给我把每个字段都加上索引”
我很惊讶,问道“为什么需要每个字段都加上索引?”
“把查询的字段都加上索引会更快”工程师信心满满
“这种情况完全可以建一个联合索引,因为是最左前缀匹配,所以operate_time需要放到最后,而且还需要把其他相关的查询都拿来,需要做一个综合评估。”
“联合索引?最左前缀匹配?综合评估?”工程师不禁陷入了沉思。
多数情况下,我们知道索引能够提高查询效率,但应该如何建立索引?索引的顺序如何?许多人却只知道大概。其实理解这些概念并不难,而且索引的原理远没有想象的那么复杂。

分类: MySQL 标签: mysql 索引 优化 慢查询