一张图读懂https加密协议

https是一种加密传输协议,网站使用https后可以避免敏感信息被第三方获取。所以我们经常看见很多银行网站或电子邮箱等等安全级别较高的服务都会采用https协议,具体表现为,https开头、显示绿色安全锁、某些浏览器地址栏变成绿色。那么具体https是怎么工作的呢?一张图读懂https加密协议。

https加密协议简介

https其实是有两部分组成:http + SSL / TLS,也就是在http上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据。具体是如何进行加密,解密,验证的,且看下图。

1. 客户端发起https请求

客户端发起https请求就是指用户在浏览器里输入一个https网址,然后连接到server的443端口。

2. 服务器端的配置

采用https协议的服务器必须要有一套SSL数字证书,需要向CA组织(如WoSign沃通CA)申请。这套SSL证书其实就是一对公钥和私钥。如果对公钥和私钥不太理解,可以想象成一把钥匙和一个锁头,只是全世界只有你一个人有这把钥匙,你可以把锁头给别人,别人可以用这个锁把重要的东西锁起来,然后发给你,因为只有你一个人有这把钥匙,所以只有你才能看到被这把锁锁起来的东西。SSL证书是网站实现https加密协议的先决条件,可以向CA机构申请免费SSL证书,也可以付费购买高级别的SSL证书。目前沃通CA提供3年期免费SSL证书申请http://freessl.wosign.com。

3. 传送证书

这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,证书过期时间等等。

4. 客户端解析证书

这部分工作是有客户端的TLS来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存在问题。如果证书没有问题,那么就生成一个随机值。然后用证书对该随机值进行加密。就好像上面说的,把随机值用锁头锁起来,这样除非有钥匙,不然看不到被锁住的内容。

5. 传送加密信息

这部分传送的是用SSL证书加密后的随机值,目的就是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了。

6. 服务段解密信息

服务端用私钥解密后,得到了客户端传过来的随机值(私钥),然后把内容通过该值进行对称加密。所谓对称加密就是,将信息和私钥通过某种算法混合在一起,这样除非知道私钥,不然无法获取内容,而正好客户端和服务端都知道这个私钥,所以只要加密算法够彪悍,私钥够复杂,数据就够安全。

7. 传输加密后的信息

这部分信息是服务段用私钥加密后的信息,可以在客户端被还原。

8. 客户端解密信息

客户端用之前生成的私钥解密服务段传过来的信息,于是获取了解密后的内容。整个过程第三方即使监听到了数据,也束手无策。

 

来自: http://freessl.wosign.com/https-xy.html (文章不错,也顺便给人家做个广告吧)

残酷的OOM

问题: 30个虚拟机一下子全死光光了,而且/var/log/message 中没有任何遗言;莫不是被攻击了?

不要瞎猜,查一下吧

  1. 因为rsyslogd死的比较早,所以 /var/log/message 没有任何有用的信息
  2. 虽然mysqld被杀了很多次,但是依然存在,是因为mysqld_safe 没有被杀,当mysqld死掉时,mysqld_safe 就会再起一个mysqld。什么?mysqld_safe 也在死亡名单中出现了?确实,后来发现了,手动重启了,且看mysqld_safe 之后的多次mysqld被杀就行了
  3. 终于VBoxSVC 被杀,所有虚拟机就全部死光光了
  4. 如果把sshd杀死了,岂不是很悲催? 参看openssh-server 的源码: https://github.com/openssh/openssh-portable/blob/8408218c1ca88cb17d15278174a24a94a6f65fe1/openbsd-compat/port-linux.c ,其中有如下逻辑:(就是说,这家伙有自我保护功能,通过调整/proc/self/oom_score_adj 或 /proc/self/oom_adj实现,其中的设置保证该进程不会被oom掉,其他进程也可以这么效仿)

     

参考资料: https://www.kernel.org/doc/Documentation/filesystems/proc.txt

Golang call C

题记:是否输出居然和是否和行尾换行有关系

代码:

why? …

因为printf是行缓冲的,不看到换行就不输出,可以在printf后面刷新标准输出:

另,在C的printf后面使用Go的fmt.Println(“^_^”)来输出一些东西,是不是就可以把C要打印的东西给输出来了呢?

代码如下:

结果发现,End 输出了,Hello world还是没输出。

原因:C的输出buffer和Go的不是一个

思考:

亲,你见过用C写的一个Hello world程序是必须有换行的吗?如下:

呃,这个确实没问题,why? C在退出的时候刷新输出缓冲了呗

说明:

To access a symbol originating from the C side, use the package name C. That is, if you want to call the C function printf() from Go code, you write C.printf(). Since variable argument methods like printf aren’t supported yet (issue 975)

翻译:如果你想调用C中的printf,那就是 C.printf(). 但是,向pringf这种可变参数个数的函数穿残还没有被支持,所以还不能直接写C.printf(). 只好自己包一下了

 

nginx 之unix socket

缘起:

曾经在nginx(1.7.4)两个地方配置过unix socket;一个是nginx日志,一个是fastcgi;但是,这两个地方有所不同。

关于日志的配置,通过unix socket (/dev/log) 写到本地的syslogd,如果syslogd重启了,则/dev/log 其实是被更新了的,但是nginx却不会自动重连,然后nginx就写log失败了。 如此,重启syslogd就得重启nginx,是多么“2”的一件事情啊!

关于fastcgi的配置,通过unix socket访问本地的php-fpm,如果php-fpm重启,则 unix socket不更新,自然影响不到nignx; 如果fpm stop then start,则unix socket会更新,但是,nginx却知道自动重连,也不会影响到nginx。(难道是因为该socket走的是stream的原因?)

注: 如果你不小心将socket文件配到了/tmp 下面,则socket文件可能是660的权限,nginx(用户如果和php-fpm不同)可能就没有权限连接该unix socket

nginx 之fail_over

问题: 默认情况下,nginx会自动failover,即: 其中一个上游服务器处理失败时会自动将请求转发到下一个上游服务器;有些情况下是不期望如此的;

但是这里没有区分上游服务器的失败原因,如果是连接失败,则自动fail_over 基本是没问题的;如果是已经发送了数据然后等待响应超时失败,可能并不想fail_over

 

避免failover的办法:

  1. 对于fastcgi: fastcgi_next_upstream off
  2. 对于proxy:  proxy_next_upstream off

如果把 proxy_next_upstream 写到fastcgi_pass 中是不会有效果的,虽然不会报错

 

可能在应用层来避免重复处理才是正道

 

关于tcp健康检查

方法1: connect then close

这种情况,上层应用会感知到一个连接的进入,并准备开始处理,然后便因为client端close而中止

方法2: send syn then receive syn-ack then send reset

这样的话,远端根本不需要完成一个tcp连接,也不会被上层应用感知到;这样需要更加底层的socket(raw socket)编程

方法3: send syn then receive syn-ack then send ack then send reset

2015-12-17 更新:

初写这篇文章时,阿里金融云SLB的tcp健康检查使用的是方法1,也是因此才写的该文章;今天发现阿里金融云SLB的tcp健康检查使用的是方法2,于是在此更新一下该文章。

2016-11-10 更新:

发现阿里金融云的SLB的tcp健康检查又不是方法2了, 阿里云文档上写的是方法2,实际上不是方法2,而是方法3,方法3更坑爹,有些web server会报client异常关闭连接

2018-8-2 更新:

SLB的HTTP模式下,健康检查允许关闭, TCP模式下不允许关闭健康检查;虽然允许设置检查其他端口来避免健康检查对某些服务的骚扰,但依然觉得很别扭;

2018-11-09更新:

对于HTTP服务,仅检查端口存活不大严格,如果进程假死,依然无法提供服务,但是端口是活的,所以,对于HTTP服务,通过HTTP请求来检查还是比较合理的,为了避免不必要的访问日志,可以对这种请求不记录访问日志

 

nmap 的半连接端口检查: