网站迁移HTTPS的一点经验

什么是HTTPS

定义

超文本传输安全协议(英语:Hypertext Transfer Protocol Secure,缩写:HTTPS,也被称为HTTP over TLS,HTTP over SSL或HTTP Secure)是一种网络安全传输协议。在计算机网络上,HTTPS经由超文本传输协议进行通信,但利用SSL/TLS来对数据包进行加密。HTTPS开发的主要目的,是提供对网络服务器的身份认证,保护交换数据的隐私与完整性。这个协议由网景公司(Netscape)在1994年首次提出,随后扩展到互联网上。

以上解释来自维基百科,反正记着传输加密,非常安全就对了。

必要性

HTTPS为什么1994年就提出来了,但是直到最近几年才开始普及呢?按我的理解有下面几点

  1. 互联网流量暴增,人们对隐私的保护越来越在意。(当然在天朝还是路漫漫)
  2. 硬件能力的提升,服务器处理能力得到了极大的提升,对于https流量的加解密过程能在几毫秒内完成。(https拖慢网站访问速度的言论在前几年是非常普遍的)
  3. 国内外大厂均转身HTTPS,整个产业链越来越完善,比如服务器提供商、云存储、CDN厂商、都已经对HTTPS做了很好的支持。
  4. 国内的流量劫持太过普遍,疯狂插广告劫持统计代码等等。最出名的莫过于某度的统计代码劫持事件。
  5. HTTPS证书的价格降低甚至免费(以Let’s Encrypt为代表)

证书的选择

证书就三类,DV、OV、EV,普通网站使用DV证书就好了。而DV证书也有收费和免费之分,我是真没看出有啥特别的区别,也就是收费的证书有效期时间长点,免费的3个月到1年为周期。

说下我自己的选择:
服务器:使用Let’s Encrypt免费证书,支持多个子域名,续签或者增加子域名的时候的非常快速简单。
CDN:直接在厂商后台申请免费1年期的赛门铁克证书

这里需要说明的是国内的阿里云、腾讯云、七牛等等提供的免费证书都是赛门铁克的免费证书,都是一家公司的产品,所以随便在哪个平台申请就好了。

CDN厂商的选择

  • 网宿、蓝讯:大厂必备,反正斗图啦这样的小网站就不考虑了。
  • 阿里云:HTTPS配置很方便,但是价格贵的离谱,0.2元/万次请求
  • 腾讯云:不对HTTPS做额外的收费,价格与HTTP的一致。看着很美好,但是我用了一段时间发现用了HTTPS后流量消耗变大、每天的峰值带宽增加了。所以不管你是用流量结算还是用带宽峰值结算,成本都是增加的。这其中必然是有不可告人的猫腻,但是整体还是比阿里的便宜。

云存储厂商的选择

国内不用多说,目前就两家比较大的

  • 又拍云:0.05元/万次请求,流量价格为0.29元/G
  • 七牛:不收取请求费,流量价格为0.36元/G

小图片比较多的话适合七牛,不然又拍的请求费弄死你,请求数产生的费用比流量产生的费用还大。当然了又拍是没有计算PUT/DELETE费用的,而七牛是对这两种请求收费的,还挺贵所以怎么选择还是要大家亲自试试。怎么用两者产生最低的流量成本也是本学问。

服务器配置过程

可以参考这篇:How To Secure Nginx with Let’s Encrypt on CentOS 7,写的浅显易懂,非常值得推荐。

总结

HTTPS很美好,对用户好对站长也好。但是运营成本会有所提升,这个就看运营者自身的考虑了。

Laravel缓存系统的设计

遇到的问题

一个业务流量上来以后,直接查询MySQL的压力是很大的,如果稍有不慎出现扫表行为就容易阻塞MySQL,轻则导致业务请求响应慢重则导致业务卡壳彻底无法使用。

Laravel 的缓存系统只设计了通用的缓存API,某些场景下使用缓存的时候,需要自己去构建缓存Key,等业务逻辑多了以后,对于Key的管理就成了一个很大的问题。

解决方式

想到这里其实我们需要的是一个通用的缓存系统,对于业务层只需要记着调用ORM提供的方法存取数据即可,不需要去理解处理缓存Key的生成、过期机制及缓存介质。

阅读全文 »

Laravel Eloquent 调用逻辑解析

前言

使用过Laravel的人应该都熟悉下面这一条语句,主要用来根据主键ID获取一条数据库记录。

Photo::find(2)

下面就从这条语句开始,逐条解析源代码的执行流程。

解析过程

本文以Laravel 5.1 LTS 为例子
所在文件:app/Models/Photo.php

namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Photo extends Model
{
//some code
}

可以看到继承了:Illuminate\Database\Eloquent\Model,打开文件可以发现并没有find方法,很简单方法不存在会触发下面的代码调用。

阅读全文 »

服务器CPU满载问题

前因

先说明一下,原先服务器是阿里云1核心2G内存的服务器,开了Redis、ES、MySQL、PHP、Nginx等等服务、外加其他一些后台常驻进程后,资源用的基本上用的是满满当当。但是php-fpm时常会报如下的错误。

[28-Oct-2016 14:25:52] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 5 idle, and 17 total children
[28-Oct-2016 14:25:53] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 16 children, there are 7 idle, and 22 total children
[28-Oct-2016 14:25:54] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 32 children, there are 9 idle, and 25 total children
[28-Oct-2016 14:25:59] WARNING: [pool www] server reached pm.max_children setting (30), consider raising it

异想天开之路

很明显嘛,系统跟你说php-fpm进程太少了,nginx转发过来的请求太多了,让你给多开几个进程,配置改起来也方便,就下面几个。

pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 20
pm.max_spare_servers = 30

然后就恶梦就逐渐开始了,刚开始还运行的好好的,后面就开始连锁反应了。

  • 内存直接爆了
  • 系统开始杀进程,内存不足还干毛活啊
  • 导致大量php-fpm进程无法响应,nginx返回给用户502错误
  • 进程被系统杀了,php-fpm又开始不断的fork新进程出来
  • 接着CPU就直接满载了
  • 然后最最可怕的东西来了,SSH完全连不上了

SSH一连接不上,那就是想修修不了啊,赶紧重启服务器,升级内存吧。当然升级内存只是其中一种方式,原先本来想把全站数据用nginx静态化掉,这样最省资源但是有个很大的问题就是数据无法即时更新。

结论

服务器的配置在不能确定会有何影响的情况下不要乱改,不然够你喝一壶的。

微信机器人无法踢人的小Bug

问题描述

昨天遇到一个比较好玩的问题,微信群的管理反馈只要群昵称带有🌺的均踢不掉。今天查到了发现是因为微信在下发群成员数据的时候会随机的下发下面两种格式的群员昵称。

第一种(emoji表情转换成UTF-8显示)

'\xe6\x89\x93\xe9\x85\xb1\xe6\xb2\xb9\xe6\xbb\xb4\xe5\xad\xa9\xe7\xba\xb8\xf0\x9f\x8c\xba'

第二种(emoji表情未转换,还是以HTML标签的形式标识的)

'\xe6\x89\x93\xe9\x85\xb1\xe6\xb2\xb9\xe6\xbb\xb4\xe5\xad\xa9\xe7\xba\xb8<span class="emoji emoji1f33a"></span>'

而收到的踢人命令是这样的:

打酱油滴孩纸🌺 飞机票

转换成UTF-8显示就是上面第二种的原始编码,所以无法踢人的原因就是机器人收到以第二种的形式编码的踢人命令,而本地保存的群员数据却是以第一种形式保存的,导致不匹配,自然就找不到群员踢不掉了。

如何解决问题

我们仔细观察第一种和第二种的编码主要的区别在于

\xf0\x9f\x8c\xba
<span class="emoji emoji1f33a"></span>

聪明的人应该可以想到了,1f33a 是的🌺的unicode标识,而 \xf0\x9f\x8c\xba 其实就是🌺的UTF-8编码。

具体可以看emoji编码表 Unicode character inspector: 🌺

所以需要解决的问题就转化成已知 unicode值1f33a,如何求得其UTF-8的编码值,求解源码如下所示,具体就不解释了。

#coding: utf-8
import re
data = '\xe6\x89\x93\xe9\x85\xb1\xe6\xb2\xb9\xe6\xbb\xb4\xe5\xad\xa9\xe7\xba\xb8<span class="emoji emoji1f33a"></span> 飞机票'
[remove_user, remove_str] = data.rsplit(' ', 1)
print remove_user
print remove_str
matches = re.findall(r"<span.+?<\/span>", remove_user)
for item in matches:
emoji_unicode = re.findall(r"emoji([\w\d]*?)\"", item)
print emoji_unicode
emoji_int = int(emoji_unicode[0], 16)
s = "\\U%08x" % emoji_int
c = s.decode('unicode-escape')
d = c.encode('utf-8')
data = data.replace(item, d)
print list(data)

获取微博登录Cookies的几种方案

为什么需要获取登录后Cookies

  1. 微博爬虫
  2. 微博图床

目前这两个项目所使用的cookies值,都是手工复制的,虽然工作的很好,但是时间久了也挺烦的。

直接模拟(方案A)

微博的登录网上已有开源方案:https://github.com/xchaoinfo/fuck-login

需要说明的一点是看现在的登录代码不是特别复杂,但是如果自己分析的话,难度还是比较大的。需要说明的是这边是直接模拟:weibo.com 上的登录框,所以每次登录的时候都需要验证码。

阅读全文 »

一个奇怪的Bug

神马Bug

最近观察了一下,用户在搜索的时候经常出现500错误,但是自己测试的时候又非常正常,这就相当蛋疼了。看laravel.log上面的错误日志,基本看不出啥玩意,还好还接了第三方的Bug系统sentry,说真的很好用,就是太贵了。

Bug出现的原因

要查Bug,先来看看用户提交上来的搜索词有哪些,下面是几个整理出来的搜索关键词。

搜索关键词 实际传输的urlencode编码 正确的urlencode编码
下一张 %E4%B8%8B%E4%B8%80%E5%BC%3F %e4%b8%8b%e4%b8%80%e5%bc%a0%3f
傻逼? %E5%82%BB%E9%80%3F %e5%82%bb%e9%80%bc%3f

我们知道只有对中文正确的编码,服务端才能正常的解析出真实的关键词,像上面的关键词的urlencode编码均出现了少字符的情况(表格内使用删除线标识缺少的字符)。到了服务器解析出来的时候直接乱码了,继而导致搜索发生500错误。

怎么修Bug

这个问题比较奇怪,以下是我猜测的几个原因

  1. 某些浏览器把urlencode出的字符给吞了
  2. 服务端在生成模板的时候发生了编码错误
  3. CDN网络在对原始网页文件进行压缩的时候,把相关字符给吞了!

第1、2种发生错误的概率比较低,但是我还是做了点修改,把页面编码给改了一下。

<meta http-equiv="content-type" charset="utf-8">
替换为
<meta http-equiv="content-type" content="text/html; charset=UTF-8">

第3种,因为目前服务器使用的是阿里的CDN网络,直接进后台关闭代码压缩即可。

ElasticSearch的一点点使用经验

为啥要使用

用户要搜索嘛,传统的mysql like语句不满足要求,需要更强大的搜索工具。

安装方法

使用添加es官方安装源的方式,这里就不重新复制一份了参考这里安装吧:官方源安装ES步骤

导入数据

创建索引首先需要创建索引

curl -XPOST http://127.0.0.1:9200/some_index -d'
{
"mappings": {
"my_type": {
"properties": {
"date": {
"type": "date",
"format": "yyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
},
"settings": {
"analysis": {
"char_filter": {
"escape_sign": {
"type": "mapping",
"mappings": [
"@=>qsdvhi" //用户搜索的时候,把@转换为某个字符串
]
}
},
"analyzer": {
"my_analyzer": {
"type": "custom",
"char_filter": ["html_strip", "escape_sign", "tsconvert"], //繁体转简单
"tokenizer": "ik_max_word", //使用IK中文分词
"filter": [ "lowercase"]
}}
}}
}'
阅读全文 »

SVN命令行导出某个时间段内某个用户所有提交过的文件列表

公司使用的是SVN来做代码的管理,经常出现的情况是每天提交代码,等开发周期结束后需要整理出所以已提交过的文件,然后同步系统一次性更新到外网去。

windows下使用tortoiseSVN

非常方便

  1. 直接右键
  2. TortoiseSVN
  3. Show log
  4. 然后选中指定的多条commit记录
  5. 下面就自动整理出所有去重后的文件列表了,然后全选复制即可。
    阅读全文 »

SSH日志分析

今天闲着仔细看了下SSH的secure日志,发现了一些有意思的东西,记录在下!

几种常见的暴力破解提示的错误

  1. Did not receive identification string from
    有人尝试使用账号密码登录你的服务器

  2. vsftpd[11273]: pam_userdb(vsftpd:auth): user ‘acount’ granted access
    vsftpd授权登录

  3. Invalid user nagios from 115.28.108.179
    又是尝试登录

  4. Received disconnect from 121.42.0.88: 11: Terminating connection
    有攻击者尝试使用一些特定的代码暴力破解服务器,然后SSHD服务终止了此行为

    阅读全文 »